Text Truncated. Only the first 1MB is shown below. Download the file for the complete contents.
NW 1 - AppleShare and Old Finders
Networking
Revised by: March 1988
Written by: Bryan Stearns March 1987
A rumor has been spread that if you use a pre-AppleShare Finder on a workstation to access AppleShare volumes, you can bypass AppleShare’s “access privilege” mechanisms.
This is not true. Access controls are enforced by the server, not by the Finder. If you use an older Finder, you are still prevented (by the server) from gaining access to protected files and folders; however, you will not get the proper user-interface feedback that you would if you were using the correct Finder: for instance, folders on the server will always appear plain white (that is, without the permission feedback you’d normally get), and error messages would not be as explanatory as those from Finders that “know” about AppleShare servers.
Further Reference:
• AppleShare User’s Guide
NW 2 - AppleTalk Interface Update
Networking M.NW.AppleTalkInterfaceUpdate
Revised by: March 1988
Written by: Bryan Stearns July 1987
M.NW.HL.AppleTalk announced that we would be moving to a simplified AppleTalk Manager interface. That interface is available now, as part of MPW 2.0 and newer.
Documentation for this new interface is contained in the AppleTalk Manager chapter of Inside Macintosh Volume V. This technical note contains some of the preliminary documentation for this interface and some useful points about information about it, and AppleTalk in general.
The original AppleTalk Pascal Interfaces, known as ABPasIntf, were designed to simplify use of AppleTalk from high-level languages. Instead, they’ve caused us a few compatibility problems. We’ve decided to encourage use of the same interface that assembly-language AppleTalk uses, a parameter-block interface in the same style as the low-level interfaces to the File and Device Managers.
The original calls are still supported (and will be for a while) as an “alternate” interface, but we suggest that you consider moving to the new “preferred” calls. Be warned that use of the original calls may cause compatibility problems with future system software. Also, new protocols (like ASP, the AppleTalk Session Protocol) are only provided with the new interfaces.
The new interface uses parameter blocks like those used by the File and Device Managers; you fill out the call-specific fields of the block, and a small amount of glue code (provided with development environments like MPW) turns the parameter block into a Control call to the appropriate AppleTalk driver.
Most calls have an interface like:
FUNCTION PSomeCall(thePBPtr: ATPPBptr; asyncFlag: BOOLEAN): OSErr;
The glue fills in the fields csCode and ioRefNum with the appropriate value for the call you’re making.
Synchronous and Asynchronous calls
You can still make calls synchronously (“do it now”) or asynchronously (“start it now, finish it soon”). If you choose to make a call asynchronously, be sure to provide a completion routine in the ioCompletion field (to be called when the call finally finishes), or poll the ioResult field of the parameter block (the call is done if ioResult is less than or equal to 0).
You must not move or dispose of a parameter block before the call finishes; when the call does complete, you are responsible for throwing the parameter block away (if you allocated it using Memory Manager routines).
Note that the alternate interfaces generated a network event on completion of an asynchronous call; this service is not provided by the preferred interfaces, partly because of future compatibility problems. See M.NW.NoNetEvents for background information.
Packed data structures
Several of the data structures used by the new interfaces are packed; Pascal doesn’t deal well with these structures. Special calls are provided for building LAP and DPP write-data structures, NBP names-table elements, and ATP buffer data structures.
For example, when registering a name (using PRegisterName), you’ll use a NamesTableEntry structure. This structure consists of a few unpacked fields, followed by an entity-name: three strings (representing the object, type, and zone fields of the name) packed together. You can call NBPSetNTE to pack the strings into the NamesTableEntry structure. When you remove the name (PRemoveName), you’ll use the entity-name by itself; you can use NBPSetEntity to pack it in.
Zone Interface Protocol
A function, GetBridgeAddress, is provided to obtain the node ID of a bridge, for use in ZIP transactions (zero is returned if no bridge is present on your network). You make ZIP calls using ATP requests, as described in the Inside AppleTalk chapter on ZIP.
Further Reference:
• The AppleTalk Manager
• Inside AppleTalk (for ZIP information)
• M.NW.HL.AppleTalk
• M.NW.NoNetEvents
NW 3 - AppleTalk Phase 2 on the Macintosh
Networking M.NW.AppleTalkPhase2
Revised by: Sriram Subramanian December 1989
Written by: Pete Helme & Sriram Subramanian August 1989
This Technical Note discusses the new features and calls available with AppleTalk Phase 2.
Changes since August 1989: Incorporated the ClosePrep and CancelClosePrep transitions and the new control calls to the .MPP driver.
AppleTalk Phase 2 is only available on Macintosh Plus or later Macintosh platforms, and it requires the installation of AppleTalk file V53, or greater. Both EtherTalk 2.0 and TokenTalk 2.0 automatically install this AppleTalk file. Developer Technical Support can supply the Phase 2 drivers for development use; however, if you need to include the Phase 2 drivers in your product, you must license them from Software Licensing. For more information, contact:
Apple Software Licensing
Apple Computer, Inc.,
20525 Mariani Avenue, M/S 38-I
Cupertino, CA, 95014
(408) 974-4667
AppleLink: SW.LICENSE
What is AppleTalk Phase 2?
AppleTalk Phase 2 contains enhancements to the routing and naming services of AppleTalk. Among these enhancements is the ability to create AppleTalk networks which support more than 254 nodes, and to do so in a manner that is, to the greatest extent possible, compatible with current AppleTalk implementations and applications. Multiple zones per network are now supported, and users can choose their machine’s zone. Benefits include improved network traffic and better router selection. New calls and features have been implemented with this enhancement and are documented in this Note.
Are AppleTalk Phase 2 Drivers Present?
So you want to use these new calls and features, but can you? First, one needs to check to see if the node is running AppleTalk Phase 2. There are two ways this can be accomplished. The easiest way is to make a _SysEnvirons call and check the returned atDrvrVersNum field. If this byte is greater than or equal to 53, then AppleTalk Phase 2 drivers are present. If, for some reason, a _SysEnvirons call is not practical or otherwise not possible, one can check 7 bytes off the device control entry for the .MPP driver for a single byte, which is the driver version (actually the low byte of the qFlags field of DCtlQHdr in the DCE). Again, if this byte is 53 or greater, AppleTalk Phase 2 is present, and the calls and features outlined in this Note may be used.
Calls to the .MPP Driver
AppleTalk Phase 2 introduces many new variables, and we highly recommend that you use the new GetAppleTalkInfo call instead of looking at MPP globals directly. In addition, on a Macintosh running the AppleTalk Internet Router software, there may be more than one .MPP driver present. These additional drivers can be found by walking through the unit table (UTableBase $11C) and looking for drivers named .MPP other than at unit slot 9. Generally, the only port of interest to you is the user port, reflected in this call as PortID 0 with a refnum of -10.
GetAppleTalkInfo
Parameter Block
--> 26 csCode word ; always GetAppleTalkInfo (258)
--> 28 Version word ; requested info version
<-- 30 VarsPtr pointer ; pointer to well known MPP vars
<-- 34 DCEPtr pointer ; pointer to MPP DCE
<-- 38 PortID word ; port number [0..7]
<-- 40 Configuration long ; 32-bit configuration word
<-- 44 SelfSend word ; non zero if SelfSend enabled
<-- 46 NetLo word ; low value of network range
<-- 48 NetHi word ; high value of network range
<-- 50 OurAddr long ; our 24-bit AppleTalk address
<-- 54 RouterAddr long ; 24-bit address of (last) router
<-- 58 NumOfPHs word ; max. number of protocol handlers
<-- 60 NumOfSkts word ; max. number of static sockets
<-- 62 NumNBPEs word ; max. concurrent NBP requests
<-- 64 NTQueue pointer ; pointer to registered name queue
<-> 68 *LAlength word ; length in bytes of data link addr
--> 70 *LinkAddr pointer ; data link address returned
--> 74 *ZoneName pointer ; zone name returned
* for extended networks only
This call is provided to simplify the task of obtaining details about the current AppleTalk network connection. The following are the parameters which this call returns:
Version is passed by the caller. The concept is similar to one used by _SysEnvirons, where a version ID is passed to the function to return a requested level of information. If the driver cannot respond because this number is too high, paramErr is returned. The current version number is 1.
VarsPtr is the pointer to AppleTalk variables. This points to the well known sysLapAddr and read header area or RHA.. This pointer may not be equal to $2D8 (ABusVars) for other than port 0.
DCEPtr is a pointer to the driver’s device control entry. See the Device Manager chapters of Inside Macintosh for details.
PortID is the port number, and it is always zero, unless a router is active and a driver refnum other than -10 is used.
Configuration is a 32-bit word of configuration flags. Currently only the following bits are returned:
31 (SrvAdrBit) is true if server node-ID was requested at open time. Note that even if server address is requested, it may be ignored by those ADEVs which do not honor it (i.e., EtherTalk, TokenTalk, etc.).
30 (RouterBit) is true if an AppleTalk Internet Router was loaded at system startup. Note that a router may be loaded, but not active.
7 (BadZoneHintBit) is true if the node’s zone name hint is invalid, thus causing a default zone to be selected.
6 (OneZoneBit) is true if only one zone is assigned to an extended network.
SelfSend (the ability for a node to send packets to itself) is non-zero if this feature is currently enabled.
NetLo is the low value of the network range. Non-extended networks always have a range of exactly one network, if the network number is known.
NetHi is the high value of the network range.
OurAddr is the 24-bit AppleTalk network address of the node. The most significant byte is always zero.
RouterAddr is the 24-bit AppleTalk address of the router from which we last heard. Users should always use this address when attempting to communicate directly with a router.
NumOfPHs, are maximum capacities for the driver. They are number of protocol
NumOfSkts, and handlers, number of static sockets, and number of concurrent NBP
NumNBPEs requests allowed, respectively.
NTQueue is a pointer to the registered names table queue. See Inside Macintosh, Volume II, The AppleTalk Manager, for NT Queue details.
LALength is passed by the caller to indicate how much (if any) of the data link address is to be copied to a user-suppled buffer (pointed to by LinkAddr). The actual length is returned by the driver. If the caller requests more bytes than the actual number, then data in the buffer after the address is undefined. The caller is responsible for providing sufficient buffer space.
LinkAddr is a pointer to a user-supplied buffer into which the data link address data is copied. If the pointer is NIL, no data is copied.
ZoneName is a pointer to a user-supplied buffer into which the node’s stored zone name is copied. If the pointer is NIL, no data is copied. The user buffer must be 33 bytes or more in size.
Calls to the .ATP Driver
KillAllGetReq
Parameter Block
--> 26 csCode word ; always KillAllGetReq (259)
--> 28 atpSocket byte ; socket on which to kill all pending
GetRequests
KillAllGetReq aborts all outstanding GetRequest calls on the specified socket and completes them with reqAborted errors (it does not close the specified socket, it only kills all pending GetRequest calls on that socket). To kill all the GetRequest calls, simply pass the desired socket number in the atpSocket field.
Result codes noErr No Error (0)
cbNotFound control block not found (-1102)
Setting the TRel Timer in SendRequest Calls
It is now possible to set the TRel timer in SendRequest or NSendRequest calls with ATP XO (exactly once) service so as not to be locked into the pre-AppleTalk Phase 2 time of 30 seconds. This is done by setting bit 2 in the atpFlags field to indicate to the driver that an extended parameter block is being used. Make a standard SendRequest call, but add the timeout constant desired in the new TRelTime field byte of the parameter block. Both nodes must be running AppleTalk Phase 2 for this feature to be supported.
The timeout constants are enumerated as follows in the lower three bits of the TRelTime ($32 offset) byte:
000 $0 TRel timer set to 30 seconds
001 $1 TRel timer set to one minute
010 $2 TRel timer set to two minutes
011 $3 TRel timer set to four minutes
100 $4 TRel timer set to eight minutes
All other values are reserved.
Parameter Block
--> 50 TRelTime byte ; indicates time to wait for TRel packet
Name Binding Protocol (NBP) Change: Wildcard Lookup
In AppleTalk Phase 2, NBP is enhanced to provide additional wildcard support. The double tilde (≈), $C5, is now reserved in the object name and type strings and used in a lookup to mean a match of zero or more characters. Thus “≈cliff” matches “cliff,” ”the cliff,” ”grazing off the cliff,” etc., and “123≈456” matches “123456,” “123zz456,” etc. At most one ≈ is allowed in any string. A single ≈ has the same meaning as a single =, which also must continue to be accepted. The ≈ has no special meaning in zone names. Clients of NBP must be aware that “old” (pre-AppleTalk Phase 2) nodes may not process this new wildcard feature correctly. This feature should probably only be used when it is known that the responding devices are running Phase 2 drivers as well.
Obtaining Zone Information Using the New .XPP Driver Calls
Previously, Zone Information Protocol (ZIP) functions were accomplished via direct ATP calls to the local router. It was rather nasty business, having to mess with the ATPUserData on subsequent calls to retain state information. We now recommend the use of the following XPP driver calls to access ZIP. Old ATP calls will continue to be supported for compatibility. It should also be noted that with Phase 2 drivers present, the .XPP driver is automatically opened by MPP.
GetZoneList
Parameter Block
--> 26 csCode word ; always xCall (246)
--> 28 xppSubCode word ; always zipGetZoneList (6)
--> 30 xppTimeout byte ; retry interval (seconds)
--> 31 xppRetry byte ; retry count
32 <unused> word ; word space for rent. see the super.
--> 34 zipBuffPtr pointer ; pointer to buffer (must be 578 bytes)
<-- 38 zipNumZones word ; no. of zone names in this response
<-- 40 zipLastFlag byte ; non-zero if no more zones
41 <unused> byte ; filler
--> 42 ziplnfoField 70 bytes ; on initial call, set first word to zero
GetZoneList is used to obtain a complete list of zones on the internet. ZipBuffPtr points to a buffer that.must be 578 bytes (ATPMaxData) in length. The actual number of zone names returned in the buffer is returned in zipNumZones. The fields xppTimeout and xppRetry contain the ATP retry interval (in seconds) and count, respectively.
The first time this call is made, the first word of the ziplnfoField should be set to zero. When the call completes, zipLastFlag is non-zero if all the zone names fit into the buffer. If not, the call should be made again immediately, without changing zipInfoField (it contains state information needed to get the next part of the list). The call should be repeated until zipLastFlag is non-zero. The 70-byte zipInfoField must always be allocated at the end of the parameter block.
xpb.zipBuffPtr = (Ptr) theBufferPtr; /* this buffer will be filled with
the packed zone names */
/* loop until zipLastFlag is non-zero or an error occurs */
while(xpb.zipLastFlag == 0 && resultCode == 0) {
resultCode = PBControl(&xpb, false);
if(resultCode == noErr) {
totalZones += xpb.zipNumZones;
/* you can now copy the zone names into the zoneBuffer */
}
DisposPtr(theBufferPtr);
DisposPtr(zoneBuffer);
}
}
GetLocalZones
Parameter Block
--> 26 csCode word ; always xCall (246)
--> 28 xppSubCode word ; always zipGetLocalZones (5)
--> 30 xppTimeout byte ; retry interval (seconds)
--> 31 xppRetry byte ; retry count
32 <unused> word ; filler
--> 34 zipBuffPtr pointer ; pointer to buffer (must be 578 bytes)
<-- 38 zipNumZones word ; no. of zone names in this response
<-- 40 zipLastFlag byte ; non-zero if no more zones
41 <unused> byte ; filler
--> 42 ziplnfoField 70 bytes ; on initial call, set first word to zero
; on subsequent calls, do not modify!
This call has the same format and procedures as GetZoneList, the difference being that GetLocalZones returns a list of zone names currently defined only on the node’s network cable rather than the entire network. The 70-byte zipInfoField must always be allocated at the end of the parameter block.
Note: The examples for GetZoneList will also work for GetLocalZones if you substitute the xppSubCode.
GetMyZone
Parameter Block
--> 26 csCode word ; always xCall (246)
--> 28 xppSubCode word ; always zipGetMyZone (7)
--> 34 zipBuffPtr pointer ; pointer to buffer (must be 33 bytes)
--> 42 ziplnfoField 70 bytes ; first word must be set to zero on every call
GetMyZone returns the node’s AppleTalk zone name. This is the zone in which all of the node’s network visible entities are registered. ZipBuffPtr points to a buffer that must be 33 bytes in length. If noBridgeErr is returned by the call, there is no internet, and the zone name is effectively an asterisk (*). The 70-byte zipInfoField must always be allocated at the end of the parameter block.
When running on a node with Phase 2 compatible drivers, we always recommend using the .XPP calls outlined in the previous section. Care was taken to keep backward compatibility with the already existing ATP ZIP calls (they are being trapped out with the Phase 2 drivers), but there are problems about which you should be aware.
• Do not rely on checking the TID (transaction ID validity bit) or other bits in the atpFlags, as some of you have been doing. The atpFlags are not guaranteed to be correct on an ATP ZIP call with a Phase 2 driver present.
• Do not repeatedly stuff the router address back into the ATPParamBlock on subsequent ATP ZIP GetZoneList calls. There exists the possibility of concurrent GetZoneList calls being made by other tasks and wrong router addresses being used (a small possibility yes, but it does exist).
The AppleTalk Transition Queue
To keep applications and other resident processes on the Macintosh informed of AppleTalk events, such as the opening and closing of AppleTalk drivers, a new transition queue has been implemented. Processes can register themselves with the AppleTalk Transition Queue, and when a significant event occurs, they will be notified of this fact. Each transition queue element has the following MPW assembly-language format:
AeQentry RECORD 0
QLink DS.L 1 ; link to next record
QType DS.W 1 ; unused
CallAddr DS.L 1 ; pointer to task record
ENDR
Three calls have been provided in the LAP Manager to add an entry, remove an entry, and return a pointer to the AppleTalk event queue header. The method for making calls to the LAP Manager is explained in the following section. The queue is maintained by the LAP Manager, so it can be active even when AppleTalk (MPP) is not.
Making a LAP Manager Call
The LAP Manager is installed in the system heap at startup time, before the AppleTalk Manager opens the .MPP driver (hence, the inclusion of the AppleTalk Transition Queue in LAP Manager rather than under .MPP). Calls are made to the LAP Manager by jumping through a low-memory location, with register D0 equal to a dispatch code that identifies the function. The exact sequence is:
MOVEQ #Code,D0 ; D0 = ID code of wanted LAP call
MOVE.L LAPMgrPtr,An ; An -> start of LAP manager (from $B18)
JSR LAPMgrCall(An) ; Call the LAP manager at entry point
LAPMgrPtr EQU $B18 ; This points to our start (more
; commonly known as ATalkHk2)
LAPMgrCall EQU 2 ; Offset to make LAP manager calls
The AppleTalk Transition Queue LAP Calls
LAddAEQ (D0=23)
Call: A0--> Entry to be added to the AppleTalk event queue.
The LAddAEQ call adds an entry, pointed to by A0, to the AppleTalk event queue.
MOVEQ #LAddAEQ,D0 ; D0 = 23 code of LAddAEQ LAP call
MOVE.L LAPMgrPtr,An ; An -> start of LAP manager (from $B18)
JSR LAPMgrCall(An) ; Call the LAP manager at entry point
LRmvAEQ (D0=24)
Call: A0--> Entry to be removed from the AppleTalk event queue.
The LRmvAEQ call removes an entry, pointed to by A0, from the AppleTalk event queue.
MOVEQ #LRmvAEQ,D0 ; D0 = 24 code of LRmvAEQ LAP call
MOVE.L LAPMgrPtr,An ; An -> start of LAP manager (from $B18)
JSR LAPMgrCall(An) ; Call the LAP manager at entry point
LGetAEQ (D0=25)
Return: A1--> Pointer to the AppleTalk event queue header.
The LGetAEQ call returns a pointer in A1 to the AppleTalk event queue header, previously described.
MOVEQ #LGetAEQ,D0 ; D0 = 25 code of LGetAEQ LAP call
MOVE.L LAPMgrPtr,An ; An -> start of LAP manager (from $B18)
JSR LAPMgrCall(An) ; Call the LAP manager at entry point
The Transitions
Each process is called at CallAddr when any significant transitions occur. A value is passed in, which indicates the nature of the event. Additional parameters may also be passed and a pointer to the task’s queue element is also passed. This is provided so processes may append their own data structures (e.g., a globals pointer) at the end of the task record, which can be referenced when they are called. Processes should follow the MPW C register conventions. Registers D0, D1, D2, A0, and A1 are scratch registers that are not preserved by C functions. The arguments passed to the process should be left on the stack, since the calling routine removes them. All other registers should be preserved.
The Open Transition
For AppleTalk open transitions, the process has the following interface:
From assembly language, the stack upon calling looks as follows:
OpenEvent RECORD 0
ReturnAddr DS.L 1 ; address of caller
theEvent DS.L 1 ; = 0 ; ID of Open transaction
aqe DS.L 1 ; pointer to task record
SlotDevParam DS.L 1 ; pointer to Open parameter block
ENDR
This routine is called only when the open routine for .MPP executes successfully. Every entry in the transition queue is called in the same order that the entries were added to the queue. If AppleTalk is already open and an _Open call is made, no process is called. The process should return a function result in D0, which is currently ignored.
A pointer to the open request parameter block is passed to the open event process for information only (i.e., the event process may not prevent AppleTalk open calls). Those fields which are of interest are OpenPB->ioPermssn, passed by the caller, and OpenPB->ioMix, which is both passed by the caller and updated by the .MPP open (see Inside Macintosh, Volume V, The AppleTalk Manager).
The Close Transition
For AppleTalk close transitions, the process has the following interface:
From assembly language, the stack upon calling looks as follows:
CloseEvent RECORD 0
ReturnAddr DS.L 1 ; address of caller
theEvent DS.L 1 ; = 2 ; ID of Close transaction
aqe DS.L 1 ; pointer to task record
ENDR
The process is being told that AppleTalk is closing, which gives the process an opportunity to close gracefully. Every entry in the event queue is called, one after the other, in the same order that the entries were added to the queue. The close action cannot be cancelled. The process should return a function result in D0, which is currently ignored.
The ClosePrep and CancelClosePrep Transitions
The AtalkClosePrep and the CancelAtalkClosePrep control calls are used by various elements of the System, such as the Chooser, to inform or query AppleTalk clients of the closing of network drivers. For example, on a machine equipped to go to sleep or to wake up, the _Sleep trap is used by such entities as sleeptimer, Finder, and Shutdown to inform AppleTalk clients that it is desirable for the the network driver (.MPP) to be closed. The _Sleep trap may be trying to do any of the following three things: request permission for sleep, alert for impending sleep, or inform that wake up is underway. The sleep request calls the following two .MPP control calls; these calls are made before sleep queue procedures are called.
The first control call, AtalkClosePrep, is used to inform or query AppleTalk clients that the network driver might be closed in the very near future. The call has the following interface:
AtalkClosePrep (csCode = 259)
Parameter Block
--> 26 csCode word ;always AtalkClosePrep
<-- 28 clientName pointer ;-> name of client using driver
Result codes noErr The AppleTalk network driver (.MPP) may be closed
closeErr The AppleTalk network driver (.MPP) may not be closed
clientName is a pointer to an identifying string that is returned only if the result is closeErr. Note that the pointer may be NIL in this case, while the pointer is always NIL if the return code is noErr.
All tasks in the AppleTalk Transition Queue are called with the event ClosePrep. The tasks can prevent driver closure with a negative response to the event call. Each task is called with the following interface:
From assembly language, the stack upon calling looks as follows:
ClosePrep RECORD 0 ;top of the stack
ReturnAddr DS.L 1 ;addr of caller
theEvent DS.L 1 ;=3
aqe DS.L 1 ;->task rec.
clientName DS.L 1 ;ptr. to ptr. to name of client
ENDR
For this event, theEvent = 3, and the task is being both informed and asked if closing the network driver is acceptable. If driver closure is acceptable, the task need only to reply affirmative (D0 = 0), or if not acceptable, deny the request (D0 ≠ 0). The task may use the event as an opportunity to “prepare to die” or may simply respond. For example, a task may prevent further sessions from forming while waiting for the actual close event.
clientName is a pointer to a field in the .MPP control call parameter block where the task may optionally store a string address. This string identifies the client who has AppleTalk in use and is denying the request to close it. This string may be used in a dialog to inform the user to take appropriate action or explain why the requested action could not be performed.
If any task responds negatively, no subsequent tasks are called. Any tasks called prior to the one that denied a query are recalled with another event, CancelClosePrep (described below), enabling them to “undo preparations to die,” and the control call then completes with a closeErr error.
From assembly language, the stack upon calling looks as follows:
CancelClosePrep RECORD 0 ;top of the stack
ReturnAddr DS.L 1 ;addr of caller
theEvent DS.L 1 ;=4
aqe DS.L 1 ;->task rec.
ENDR
For this event, theEvent = 4, and the task is being informed that although it has recently approved a request to close the network driver, a subsequent task in the AppleTalk Transition Queue has denied permission. This event permits the task to undo any processing that may have been performed in anticipation of the network driver being closed. The process should return a function result in D0, which is currently ignored.
The second new control call, CancelAtalkClosePrep, is used to undo the effects of a successful AtalkClosePrep control call. Even though all queried tasks in the AppleTalk Transition Queue approved of network driver closure, other conditions may exist after making the AtalkClosePrep control call which prohibit network driver closure. In this case, it is necessary to recall all tasks to undo any processing that may have been performed in anticipation of the network driver being closed. The control call to do this has the following interface:
CancelAtalkClosePrep (csCode = 260)
Parameter Block
--> 26 csCode word ;always CancelAtalkClosePrep
Result codes noErr Nothing could possibly go wrong
All tasks in the AppleTalk Transition Queue are called with the event CancelClosePrep as described above.
Note: The use of the low-memory global ChooserBits ($946) is no longer an acceptable means of preventing AppleTalk from closing when AppleTalk Phase 2 is present. Transitions other than defined above must be ignored and are reserved for future implementation. In the future transitions may be defined for notifying processes when a change in zone name occurs.
Potential Compatibility Problems
Using DDP and Talking to Routers
If, for some reason, you need to talk to any router via DDP, always use the GetAppleTalkInfo call outlined in this Note to get the router’s actual 24-bit address.
The WriteLAP function (csCode = 243) to the .MPP driver is no longer supported, since a node is no longer identified only by its eight-bit (LAP) node ID.
On a Macintosh running the AppleTalk Internet Router software, the SelfSend flag is always set, so if you try to clear this flag using the PSetSelfSend call (Inside Macintosh, Volume V-514), you will get an error.
Further Reference:
• Inside AppleTalk
• Inside Macintosh, Volume II, The AppleTalk Manager
• Inside Macintosh, Volume V, The AppleTalk Manager
• EtherTalk and Alternate AppleTalk Connections Reference, May 5, 1989—Draft (DTS)
• AppleTalk Phase 2 Protocol Specification (DTS)
• Macintosh Portable Developer Notes (DTS)
NW 4 - ASP and AFP Description Discrepancies
Networking
Written by: Mark Bennet August 1988
The descriptions of the AppleTalk Session Protocol and AppleTalk Filing Protocol functions within the body of the AppleTalk Manager chapter are incorrect and conflict with those in the Summary of the AppleTalk Manager. This technical note resolves the discrepancy.
The descriptions of the AppleTalk Session Protocol and AppleTalk Filing Protocol functions which are described on pages 534 through 548 of Inside Macintosh Volume V conflict with the descriptions in the Summary of the AppleTalk Manager section, pages 554 through 559. The descriptions in the Summary of the AppleTalk Manager section are correct and should be followed.
The Summary of the AppleTalk Manager does not, however, present a description of the correct meaning of the arrows next to the parameter names in the function descriptions. The meaning of the arrows is equivalent to the one given to them in the descriptions of other Operating System calls, i.e.:
Arrow Meaning
Æ Parameter is passed
¨ Parameter is returned
´ Parameter is passed and returned
Further Reference:
• The AppleTalk Manager
NW 5 - High-Level AppleTalk Routines
Networking
Revised by: March 1988
Written by: Fred A. Huxham May 1987
What you need to do in order to use high-level AppleTalk routines depends upon the interfaces you are using. Some differences are outlined below.
MPW before 2.0
When calling the old high-level AppleTalk routines, many programmers get mysterious “resource not found” errors (-192) from such seemingly harmless routines as MPPOpen. The resource that is not being found is ‘atpl’, a resource that contains all the glue code to the high-level routines. In order to use the high-level routines, your application must have this resource in its resource fork. The ‘atpl’ resource is included in a file called “AppleTalk” with any compilers that use this outdated version of the AppleTalk interface.
MPW 2.0 and newer
A newer version of the alternate interfaces is available in MPW 2.0; it includes bug fixes and increased Macintosh II compatibility. With this version of the interface, the ‘atpl’ resource is no longer used. Glue code is now linked into your application.
This will be the final release of the current-style interface. It will be supported for some time as the alternate interface. We have moved to a more straightforward and simple preferred interface, which is also implemented in MPW 2.0 and newer, and is described in the AppleTalk Manager chapter of Inside Macintosh vol. V. Developers are free to continue to use the alternate interface, but in the long run it will be advantageous to move to the preferred interface.
Third Party Compilers
Third party compilers use interfaces that are built from Apple’s MPW interfaces. Some compilers may not have upgraded to the new interfaces yet. Contact the individual compiler manufacturers for more information.
Further Reference:
• The AppleTalk Manager
• Inside AppleTalk
• AppleTalk Manager Update
NW 6 - KillNBP Clarification
Networking
Written by: Mark Bennett August, 1988
This technical note clears up some confusion regarding the Name Binding Protocol KillNBP function.
The description of the PKillNBP function on page 519 of Inside Macintosh Volume V is somewhat confusing. The data type of the parameter thePBptr is incorrectly given as ATPPBPtr and the pointer to the queue element from the NBP call to be aborted is incorrectly given as being passed in aKillQEl. The following is a correct description of the KillNBP function:
KillNBP function
FUNCTION PKillNBP (thePBptr: MPPPBPtr; async: BOOLEAN) : OSErr;
Parameter block
Æ 26 csCode word Always PKillNBP
Æ 28 nKillQEl pointer Pointer to queue element
Further Reference:
• The AppleTalk Manager
NW 7 - Avoid Use of Network Events
Networking
Revised by: March 1988
Written by: Bryan Stearns July 1987
Future System software enhancements will not support network events. This note gives hints on weaning your application from the use of network events.
What are network events?
When the Event Manager was designed, an event number was reserved for future support of “network events”. Later, when the AppleTalk Pascal Interfaces were written, a completion routine was created that, when an asynchronous AppleTalk operation finished, would post an event using networkEvt in the evtNum field.
Only the AppleTalk Pascal Interfaces generate network events. Assembly-language users of the AppleTalk drivers (and those who called the AppleTalk drivers directly from high-level languages, using PBControl calls) either provide a completion routine of their own, or poll the ioResult field of the parameter block passed with the call (when ioResult became negative or zero, the call is complete).
Why not use network events?
In some cases, network events can be lost. If the Event Manager finds that the queue is full while posting an event, it discards the oldest event. In a situation (such as a server) where multiple asynchronous ATP requests may complete at once, there is a chance that events may be dropped off the end of the queue. This is more likely if the same machine is also handling user-interface events (like keypresses and mouse actions).
Also, in developing improvements to our operating system, it has become apparent that to continue support of network events, we would have to compromise future enhancements to our system. So, future versions of the Macintosh operating system may ignore network events instead of passing them to the application.
How can I tell that my calls have completed without using network events?
As described on page II-275 of Inside Macintosh, you can poll the abResult field of the call’s ABusRecord; when this value becomes negative or zero, the call has completed. You can do this in your main event loop.
With this technique, you can ignore any network events returned by GetNextEvent, since the AppleTalk Pascal Interfaces will be posting events anyway. If your application starts enough asynchronous operations, it’s possible that their network events will cause other non-network events to be lost. To prevent this, you should call FlushEvents(networkMask,0) frequently to purge any accumulated network events from the event queue.
You may also consider using the new preferred high-level interface calls; see M.NW.AppleTalk for more information.
Further Reference:
• AppleTalk Manager
• M.NW.AppleTalk
NW 8 - Opening AppleTalk
Networking
Written by: Mark Bennett February 1989
This Technical Note describes the most effective, safe, and compatible way to open the AppleTalk drivers, .MPP and .ATP.
The process of opening the AppleTalk drivers, .MPP and .ATP, can be greatly simplified. The AppleTalk Manager chapters of Inside Macintosh describe the calls MPPOpen and ATPLoad for use by high-level languages. They also describe the process of examining low-memory globals SPConfig and PortBUse before calling _Open for assembly language use of AppleTalk.
Starting with the 128K ROM, the .MPP driver already has all the code built in for checking the low-memory globals SPConfig and PortBUse before trying to complete the _Open call. Furthermore, the .MPP driver will automatically open the .ATP driver as part of its opening process. Therefore, since all of the required checks are made inside the driver itself, we recommend that a simple _Open call be made to the .MPP driver when you need to use AppleTalk. In a high-level language like Pascal, this call would look like the following:
result := OpenDriver('.MPP', refnum);
In C:
result = OpenDriver("\p.MPP", &refnum);
And in assembly language:
openAT SUB.W #ioQElSize,SP ; Make space for paramblock on stack
; since _Open is always synchronous. ; Using .W is slightly more efficient
; and is safe since ioQElSize is small.
MOVE.L SP,A0 ; Point A0 to paramblock.
LEA mppName,A1 ; Point A1 to driver name.
MOVE.L A1,ioFileName(A0); Put pointer to name in paramblock.
CLR.B ioPermssn(A0) ; Clear so won't look like OpenDeskAcc.
_Open
MOVE.W ioRefNum(A0),D1 ;You might want this later. Who knows?
ADD.W #ioQElSize,SP ; Reclaim space on stack.
RTS ; D0 contains result code.
mppName DC.B 4
DC.B '.MPP'
By using just the simple _Open call to the .MPP driver, you can ensure that your code will be compatible with future versions of AppleTalk that might not make use of low-memory globals.
The verify flag indicator byte (verifyFlag) of the AppleTalk RegisterName function should always be set TRUE in published code.
The AppleTalk chapter of Inside Macintosh, Volume II-322, in describing the RegisterName function, states:
“If verifyFlag is TRUE, RegisterName checks on the network to see if the name is already in use, and returns a result code of nbpDuplicate if so.”
Note that verifyFlag should always be TRUE in published code. The design of the Name Binding Protocol (NBP) requires that an entity name be unique. The way RegisterName ensures this uniqueness is by broadcasting a lookup request for the registered name. If any entity responds, then RegisterName knows that the name would not be unique and returns an error. Some developers, in anticipating the time delay involved in broadcasting a lookup request and waiting for a response, have opted to set verifyFlag to FALSE, not realizing the potential danger in doing so.
Apple provides verifyFlag for experimental or developmental purposes, such as narrowing down a problem in registering a name on a network. Always make sure that code which ships has verifyFlag set to TRUE.
Further Reference:
• Inside Macintosh, Volume II-261, The AppleTalk Manager
NW 10 - AppleShare Foreground Applications
Networking M.NW.AppleShareApp
Revised by: Jim Luther July 1992
Written by: Fred A. Huxham November 1987–March 1988
This Technical Note outlines the requirements and restrictions of an AppleShare foreground application (AppleShare foreground applications are called concurrent server applications in the AppleShare File Server Administrator’s Guide). This information pertains only to AppleShare system software versions 1.1 through 2.0. AppleShare version 3.0 and Macintosh file sharing run under Macintosh System 7. AppleShare foreground applications are not necessary and are not supported by AppleShare version 3.0 or Macintosh file sharing.
Changes since March 1988: Added note that AppleShare version 3.0 and Macintosh file sharing don’t support AppleShare foreground applications. Added additional notes about AppleShare foreground applications.
An AppleShare server requires a dedicated Macintosh. The server, however, is implemented as an interrupt-driven application that runs in the system heap of the server machine. This allows the running of a concurrent or foreground application that will live in the application heap of the server machine. An example of a foreground application is LaserShare, the LaserWriter spooler available from Apple.
An AppleShare foreground application has a few additional restrictions and requirements beyond that of a normal Macintosh application:
1. In order for AppleShare to recognize your program as a foreground application, it must contain a resource of type 'fgnd', ID=1, containing a longword of $00000000.
2. Do not make any file system calls outside of server volumes’ Server Folders. If a foreground application needs to create files, it is recommended that the application create a folder inside the Server Folder and then create all its files within that folder. For example, all print spooler or E-mail files must reside within the Server Folder, and preferably, within a folder that is inside the Server Folder. To find the Server Folder,
• Make a PBHGetVlnfo call on the volume.
• Examine ioVFndrInfo[8] (long integer).
• If ioVFndrInfo[8] is nonzero, it is the directory ID of the Server Folder.
3. Do not make file system calls or in any way modify the AppleShare server application, the Parallel Directory Structure, or the user or group databases within the Server Folder of any volume. Also, do not rely on the presence or formats of these structures, as they are subject to change!
4. Do not eject or unmount a volume that is not in drive 1 or 2.
5. Do not call the Shutdown trap; instead, quit by calling ExitToShell or by dropping out of the main event loop.
In addition to these restrictions, here are a few other things that are good to know when writing an AppleShare foreground application.
Multiple AppleShare Foreground Application Support
Although you can install multiple AppleShare foreground applications on an AppleShare server, only one can be active at a time. Since the AppleShare Admin application is an AppleShare foreground application, users will have to quit Admin to run your application and quit your application to run Admin.
Number of Open Files Allowed
Any files opened by an AppleShare foreground application count toward the maximum number of open files allowed on the AppleShare file server. See Macintosh Technical Note #216, “AppleShare and File-Sharing Limits,” for the number of open files allowed on a particular AppleShare file server.
How Much Memory Does an AppleShare Foregound Application Get?
Foreground applications are launched by an AppleShare file server, so AppleShare decides how big your application heap will be. First AppleShare reads your 'SIZE' resource. It uses ID 0 (the Finder-created 'SIZE' resource) if it is available. It uses ID -1 (the default 'SIZE' resource created by the programmer) if ID 0 isn’t available. It uses any other 'SIZE' resource it can find if IDs 0 and-1 aren’t there. If no 'SIZE' resources are found, then AppleShare uses 196 KB for the size and the minimum size. If your application has a 'SIZE' less than 128 KB, then 128 KB is used for the size and the minimum size.
AppleShare then attempts to allocate the minimum size for your application (as found above). If successful, AppleShare sets the system cache to 32 KB (the minimum). (At this point, your application could still be launched if any of the following things fail.) Then, AppleShare attempts to allocate the default size for your application (as found above). After that, AppleShare gives any remaining memory back to the system cache.
Further Reference:
• AppleShare File Server Administrator’s Guide
• Macintosh Technical Note #216, AppleShare and File-Sharing Limits
NW 11 - AppleShare and File-Sharing Limits
Networking M.NW.AppleShareLimits
Revised by: Jim Luther July 1992
Written by: Mark Bennett October 1988
This Technical Note describes some machine-dependent limits of current versions of AppleShare file servers (including Macintosh file sharing).
Changes since October 1988: Added information for AppleShare system software version 3.0 and Macintosh file sharing.
The following chart lists some current AppleShare limits that are based upon the chosen server platform and memory configuration. The limits that otherwise might be present on a workstation are still in effect and are not affected by the workstation being logged on to an AppleShare server. These limits will change in the future.
AppleShare 1.1 and 2.0 Limits
Server: Server:
Macintosh Plus, SE, Macintosh II With
Description of Limit or II With 1 MB More Than 1 MB
Number of Users 25 50
Number of Locked Ranges 1000 2000
Number of Open Files 80 160
Number of Volumes 16 16
AppleShare 3.0 and Macintosh File-Sharing Limits
File Server: File Server:
Description of Limit Macintosh File Sharing AppleShare 3.0
Number of Users 10 120*
Number of Locked Ranges 200 2400*
Number of Open Files 346* 346**
Number of Share Points 10 50
* The maximum number of users supported by AppleShare version 3.0 can be adjusted with the AppleShare Admin application or with the SCSetSetupInfo AppleShare Server Control call. AppleShare version 3.0 allocates 20 locked ranges per user.
** This is the maximum number of file control blocks (FCBs) allowed by the Macintosh File Manager. The system and any applications running on the server Macintosh (including the file server) will use some of those available FCBs.
Further Reference:
• AppleShare File Server Administrator’s Guide
• Macintosh Technical Note #167, AppleShare Foreground Applications
NW 12 - AppleShare-able Applications and the Resource Manager
Networking
Revised by: March 1988
Written by: Bryan Stearns March 1987
Normally, applications on an AppleShare server volume cannot be executed by more than one user at a time. This technical note explains why, and tells how you can enable your application to be shared.
The Resource Manager versus Shared Files
Part of the explanation of why applications are not automatically sharable is based on the design of the Resource Manager. The Resource Manager is a great little database. It was originally conceived as a way to keep applications localizable (a task it has performed admirably), and was found to be an excellent foundation for the Segment Loader, Font Manager, and a large part of the rest of the Macintosh operating system.
However, it was never designed to be a multi-user database. When the Resource Manager opens a resource file (such as an application), it reads the file’s resource map into memory. This map remains in memory until the resource file is closed by the Segment Loader, which regains control when the application exits. Sometimes it is necessary to write the map out to disk; normally, this is only done by UpdateResFile and CloseResFile.
If two users opened the same resource file at the same time, and one of them had write access to the file and added a resource to it, the other user’s Resource Manager wouldn’t know about it; this would make the other user’s copy of the file’s original resource map invalid. This could cause (at least) a crash; if both users had write access, it’s not unlikely that the resource file involved would become corrupted. Also, although you can tell the Resource Manager to write out an updated resource map, there’s no way for another user to tell it to refresh the copy of the map in memory if the file changes.
What does all this have to do with running my application twice?
Your application is stored as a resource file; code segments, alert and dialog templates, etc., are resources. If you write to your application’s resource file (for instance, to add configuration information, like print records), your application can’t be shared.
In Apple’s compatibility testing of existing applications (during development of AppleShare), we found quite a few applications, some of them quite popular, that wrote to their own resource files. So we decided, to improve the safety of using AppleShare, to always launch applications using a combination of access privileges such that only one user at a time could use a given application (these privileges will be discussed in a future Technical Note). In fact, AppleShare opens all resource files this way, unless the resource file is opened with OpenRFPerm and read-only permission is specified.
But my application doesn’t write to itself!
We realize that many applications do not. However, there are other considerations (covered in detail, with suggestions for fixes, in “Application Development in a Shared Environment”, available from APDA ). In brief, here are the big ones we know about:
• Does your application create temporary files with fixed names in a fixed place (such as the directory containing the application)? Without AppleShare’s protection, two applications to use the same temporary file could be disastrous.
• Is your application at least “conscious” of the fact that it may be in a multi-user environment? For instance, does it work correctly if a volume containing an existing document is on a locked volume? Does it check all result codes returned from File Manager calls, and ResError after relevant Resource Manager calls?
OK, I follow the rules. What do I do to make my application sharable?
There is a flag in each file’s Finder information (stored in the file’s directory entry) known as the “shared” bit. If you set this bit on your application’s resource file, the Finder will launch your application using read-only permissions; if anyone else launches your application, they’ll also get it read-only (their Finder will see the same “shared” bit set.).
Three important warnings accompany this information:
• The definition of the “shared” bit was incorrect in previous releases of information and software from Apple. This includes the June 16, 1986 version of M.TB.Finder Flags (fixed in the March 2, 1987 version), as well as all versions of ResEdit before and including 1.1b3 (included with MPW 2.0). For now, the most reliable way to set this bit is to get the 1.1b3 version of ResEdit, use it to Get Info on your application, and check the box labeled “cached” (the incorrect documentation upon which ResEdit et al.] was based called the real shared bit “cached”; the bit labeled as “shared” is the real cached bit [a currently unused but reserved bit which should be left clear]).
• By checking this bit, you’re promising (to your users) that your application will work entirely correctly if launched by more than one user. This means that you follow the other rules, in addition to simply not writing to your application’s own resource file. See “Application Development for a Shared Environment,” and test carefully!
• Setting this bit has nothing to do with allowing your application’s documents to be shared; you must design this feature into your application (it’s not something that Apple system software can take care of behind your application’s back.). You should realize from reading this note, however, that if you store your document’s data in resource files, you won’t be able to allow multiple users to access them simultaneously.
Further Reference:
• The Resource Manager
• “Application Development in a Shared Environment”
• M.TB.Finder Flags
NW 13 - AppleTalk: The Rest of the Story
Networking
Updated by: Rich Kubota and Jim Luther January 1993
Written by: Rich Kubota and Scott Kuechle February 1992
This Technical Note discusses the updates and modifications to a number of facets of the lower levels of AppleTalk Phase 2 since the release of Inside Macintosh Volume VI. Topics range from discussion of the new Datagram Delivery Protocol (DDP) layer calls to the AppleTalk Multiple Node Architecture to a discussion at the driver level of the new Multivendor ADEV Architecture. Most of the information presented here concerns AppleTalk versions 56 through 58; however, additional material is presented to clarify and correct material presented in other AppleTalk documentation relating to all versions of AppleTalk.
Reordered subjects according to the order of the AppleTalk version in which the feature was first implemented. Added a table of contents to make it easier to find material. Added a discussion on Multivendor ADEV Architecture, the .TOKN driver interface, plus information on making AppleTalk drivers compatible with virtual memory under system software version 7.0.x. Added a description of the change to the .ENET interface presented by the Apple SONIC-based Ethernet drivers. Added socket listener sample code. Added AppleTalk version list.
Changes since September 1992: Corrected the .TOKN interface to remove reference to the A1 register on packet reception. Described a bug with the LAPAddATQ and LAPRmvATQ glue code that exists in the MPW Interface.o library file, and published an Assembler glue code file to work around the problem. Described a change to the .ENET EGetInfo call interface. Described a change to the 'atlk' AGetInfo call required of ADEVs to support SNMP (Simple Network Management Protocol). Discussed other changes required for .TOKN and .ENET support of SNMP. Provided additional clarification to the LAP Manager calls, LRdDispatch and LWrtInsert. Presented a correction to the ENET.h header file supplied with MPW 3.2.x.
Introduction 2
Where Can I Get the Latest Version of AppleTalk? 3
The 'atkv' Gestalt Selector 4
Sample Socket Listener 4
Socket Listener Review 5
Timing Considerations for LocalTalk 5
Register Usage 5
Socket Listener Overview 6
Socket Listener Assembler Code 7
Initializing the Socket Listener 12
Using the Socket Listener 14
The AppleTalk Transition Queue 15
Bug with LAPAddATQ and LAPRmvATQ Glue Code 16
Calling the AppleTalk Transition Queue 18
Standard AppleTalk Transition Constants 18
The Flagship Naming Service 19
The ATTransNameChangeAskTask Transition 19
The ATTransNameChangeTellTask Transition 20
The ATTransCancelNameChange Transition 20
System 7.0 Sharing Setup cdev / Flagship Naming Service Interaction 21
Distinguishing Apple’s SONIC-Based Ethernet Systems 41
Correction to the ENET.h Header File 42
AppleTalk Multiple Node Architecture 42
What Is It? 43
Glue Code For Multinode Control Calls 43
Things You Need to Know When Writing a Multinode Application 45
AddNode (csCode=262) 46
RemoveNode (csCode=263) 47
Receiving Packets 47
Sending Datagrams Through Multinodes 48
NetWrite (csCode=261) 48
AppleTalk Remote Access Network Number Remapping 49
Is There a Router on the Network? 49
New for AppleTalk ADEVs 49
AGetInfo (D0=3) 50
AAddNode (D0=9) 51
ADelNode (D0=10) 52
AGetNodeRef (D0=11) 53
AOpen (D0=7) 53
AClose (D0=8) 54
AInstall (D0=1) 54
AShutDown (D0=2) 54
Receiving Packets 54
Defending Multinode Addresses 55
Corrections/Clarifications to the LAP Manager 55
LRdDispatch (DO = 1) 55
LWrtInsert (DO = 2) 55
AppleTalk Version Information 56
Contacting Apple Software Licensing 57
Introduction
This Tech Note differs from previous revisions in that the subjects have been reordered. The topics are presented according to the order of the AppleTalk version in which the feature was first implemented. You can find new topics and modifications to this Tech Note by looking for material set off by change bars in the margins.
The first section in this Note, “The 'atkv' Gestalt Selector,” discusses the new Gestalt selector 'atkv', which provides version information when AppleTalk is available.
The next section, “Sample Socket Listener,” presents a sample socket listener, including initialization code to assist high-level language programmers. There socket listener comments describe in detail the basic functions of packet handling at the data link layer.
The next section, “The AppleTalk Transition Queue,” discusses the AppleTalk Transition Queue including its support for the Flagship Naming Service, AppleTalk Remote Access, and changes to processor speed that can affect LocalTalk and other processes dependent on processor speed. Included is Pascal source code for checking whether the Phase 2 LAP Manager exists to support the Transition Queue mechanism, plus sample Transition Queue handlers written in both C and Pascal. This section includes a description of an important bug that exists in the glue code, implemented for the LAPAddATQ and the LAPRmvATQ functions. The glue code is from the MPW Interface.o file. Replacement glue routines are provided to work around the problem for both MPW and Think programmers.
The section “Multivendor ADEV Architecture” presents the Multivendor ADEV Architecture, which allows for Ethernet and token ring cards from multiple vendors to be installed on the same system. Included is a description of the functionality of the new driver shells for Ethernet and token ring, plus a description of the .TOKN interface required for compatibility with the new ADEV Architecture.
The section “Driver Considerations for Virtual Memory” shows how to modify driver code for compatibility with system software version 7.0 virtual memory.
The section “SONIC-Based Ethernet Driver Software Interface Change” presents a change to the .ENET interface that resulted from the implementation of the SONIC Network Interface Controller on the Ethernet NB Card and in the Macintosh Quadra computer’s built-in Ethernet. The change concerns the EGetInfo function, which now returns additional network information for Apple Ethernet products based on the SONIC chip.
The section “Correction to the ENET.h Header File” presents a correction to the header file for programs that will make a parameter block Control call to the .ENET, .TOKN, or .FDDI driver, to add or delete multicast addresses. This problem applies only to C programs that are written to include the ENET.h file supplied with MPW version 3.2.x and with Think C versions 5.0 to 5.0.4.
The section “AppleTalk Multiple Node Architecture” discusses the new program interfaces to the AppleTalk Multiple Node Architecture. The new architecture was developed to support multiple node capability on the Macintosh computer, which allows the Macintosh to present itself as separate entities, or unique nodes on the network. The AppleTalk Remote Access program uses multinode capability to implement Remote Access functionality. This section presents the Datagram Delivery Protocol (DDP) interface for multinode AppleTalk for applications to take advantage of this new functionality. This Note, however, does not discuss the Remote Access program.
The section “New for AppleTalk ADEVs” presents the changes required of an ADEV’s 'atlk' code resource for compatibility with the AppleTalk Multinode Architecture. While we recommend that developers of Ethernet and token ring network hardware conform to the specifications of the Multivendor ADEV Architecture, this information is presented for those developers of network products for which Apple does not supply an ADEV.
The final section, “AppleTalk Version Information,” lists the various versions of AppleTalk, and the new products that require the support of the AppleTalk version.
Where Can I Get the Latest Version of AppleTalk?
For testing purposes, the latest version of AppleTalk and related software is available on the latest Developer CD Series disc, on AppleLink on the Developer Services Bulletin Board, and on the Internet through anonymous FTP to ftp.apple.com (130.43.2.3). It can be installed by using the Network Software Installer.
The 'atkv' Gestalt Selector
The 'atkv' Gestalt selector is available beginning with AppleTalk version 56 to provide more complete version information regarding AppleTalk, and as an alternative to the existing 'atlk' Gestalt selector. Beginning with AppleTalk version 54, the 'atlk' Gestalt selector was available to provide basic version information. The 'atlk' selector is not available when AppleTalk is turned off in the Chooser. It is important to note that the information between the two resources is provided in a different manner. Calling Gestalt with the 'atlk' selector provides the major revision version information in the low-order byte of the function result. Calling Gestalt with the 'atkv' selector provides the version information in a manner similar to the 'vers' resource. The format of the LONGINT result is as follows:
byte; /* Major revision */
byte; /* Minor revision */
byte development = 0x20, /* Release stage */
alpha = 0x40,
beta = 0x60,
final = 0x80, /* or */ release = 0x80;
byte; /* Nonfinal release # */
For example, passing the 'atkv' selector in a Gestalt call under AppleTalk version 57 gives the following LONGINT result: 0x39008000.
Note: With the release of the System 7 Tuner product, AppleTalk will not be loaded at startup, if prior to the previous shutdown AppleTalk was turned off in the Chooser. Under this circumstance, the 'atkv' selector is not available. If the 'atkv' selector is not available under System 7, this is an indicator that AppleTalk cannot be turned on without doing so in the Chooser and rebooting the system.
Sample Socket Listener
The preferred AppleTalk calls presented in Inside Macintosh Volume V, page 513, do not include a preferred style call for DDPRead. As a result developers are faced with the prospect of writing their socket listeners and using the POpenSkt function when upgrading their programs. Inside Macintosh Volume II, page 324, presents an overview of how socket listeners should function. Inside Macintosh states that socket listeners, as well as protocol handlers, need to be written in assembly code, since parameters are passed in registers. To assist high-level programmers with implementing a socket listener, the generic listener code is provided. The following code demonstrates how to do the following:
• buffer multiple packets
• return DDP/LAP header information that has already been read into the Read Header Area (RHA) by DDP
• calculate and compare the packet checksum when a packet uses a long DDP header, and includes the checksum value
Some of the things that the listener sample does not do, which you might wish to implement, are the following:
• Check the DDP type and ignore any packets that don’t match the desired type(s) that you’re interested in.
• Check the source node ID and ignore any packets that don’t come from the desired node(s).
• If the socket listener is used by more than one socket, it could route the packets differently based on the socket number found in D0.
• The socket listener does not handle the implementation of a completion routine to be executed when the packet is processed.
The example listener code includes an initialization routine which the listener client uses to notify the listener code of the “available” and “used” buffer queues. A high-level procedure is provided to demonstrate the initialization of the listener, and the use of the socket listener.
Socket Listener Review
The reader is advised to refer to Inside Macintosh Volume II, pages 324 to 330, for a description of protocol handlers, socket listeners, and data reception in the AppleTalk Manager over LocalTalk. The same architecture applies to AppleTalk on Ethernet and token ring. With the advent of AppleTalk Phase 2, the size of the Read Header Area (RHA) has been expanded to accommodate the long DDP header.
After every ReadPacket or ReadRest call, the listener code must check the Z (Zero) condition code for errors. If an error is detected from ReadPacket, the code must not call ReadRest.
It is the responsibility of the socket listener code to check for the existence of the DDP checksum. In contrast with the Frame Check Sequence that the hardware uses to verify the frame, the DDP checksum is implemented in extended DDP headers to verify that the packet data is not corrupted by memory or data bus errors within routers on the internet. If the checksum has been entered, then the socket listener code must calculate the checksum after the packet has been read in, and compare the computed value with the passed checksum value. The sample listener code demonstrates this check and calculation of the checksum. The listener code sets a flag that the program can check to determine whether the checksum matched or not.
The record structure presented in this sample returns the DDP type, destination node ID, source address in AddrBlock format, the hop count, the size of the packet, a flag to indicate whether a checksum error occurred, followed by the actual datagram. The record structure can be extended to return additional information, such as the tick count at the time the socket handler was called.
Timing Considerations for LocalTalk
If LocalTalk is being used, your socket listener has less than 95 microseconds (best case) to read more data with a ReadPacket or ReadRest call. If you need more time, you might consider reading another 3 bytes into the RHA to buy another 95 microseconds. Remember that the RHA may only have 8 bytes still available.
Register Usage
When the socket listener is called, the registers will be set up as follows:
Register(s) Contents
A0-A1 SCC addresses used by MPP
A2 Pointer to MPP’s local variables
A3 Pointer to next free byte in RHA
A4 Pointer to ReadPacket {JSR (A4)} and ReadRest {JSR 2(A4)} jump table
D0 This packet’s destination socket number
D1 Number of bytes left to read in packet
• Registers D0, D2, and D3 can be used freely throughout the socket listener. A6, and D4 to D7 must be preserved.
• From entry to socket listener until ReadRest is called:
The A5 register can be used.
Registers A0–A2, A4, and D1 must be preserved.
• From ReadRest until exit from socket listener:
The A5 register must be preserved.
Registers A0–A3 and D0–D3 are free to use.
You should assume only 8 bytes are still available in the RHA for your use. The RHA will contain one of the following:
Socket Listener Overview
The sample socket listener utilizes two standard operating system (OS) queues (see Inside Macintosh Volume II, page 372), a free queue of available buffers that the listener uses to fill with incoming datagrams. The second linked list is a used queue of buffers that the listener has processed, but that have not been processed by the listener client. The SL_InitSktListener routine is called to pass the listener the pointers to the two OS queues.
When the listener is called to process a packet, the listener checks whether there is an available buffer record in the free queue by checking that qHead element of the free queue is not nil. If so, then the listener sets register A3 to point to the buffer_data element of the record and calls the ReadRest routine. If there is no available buffer record, the packet is ignored by calling ReadRest with a buffer size value of 0. Maybe the next time a packet is handled, a buffer will be available. If an error occurs during the ReadRest function, then the listener simply returns to the caller.
If the packet is successfully read, the listener processes the header information. The header information has been stored by the hardware driver in the MPP local variable space pointed to in register A2. The listener code fills in the hop count field of the packet buffer record and determines the packet length. The listener then figures out whether it is dealing with a short or extended DDP header and fills in the remaining fields of the packet buffer. A check is made to determine whether the checksum field of the DDP header is nonzero. If the field is nonzero, the value is passed to the SL_DoChkSum function to verify that the resulting checksum is zero. If the resulting checksum is nonzero, the buffer_CheckSum field is set to ckSumErr, -3103, otherwise the field is set to noErr. Finally, the listener Enqueues the packet buffer into the used queue and Dequeues it from the free queue before returning to the caller.
The calling program periodically checks the QHead element of the used queue. When QHead is no longer nil, a packet is available for processing. The program processes the packet buffer. When finished, the packet buffer is Enqueued into the free queue and Dequeued from the used queue. The program might then check for additional packets in the used queue and process them in the same manner.
The program needs to define a sufficient number of packet buffers so that the listener has buffers available in the free queue between times when the program checks the used queue and processes incoming packets.
; Function SL_InitSktListener(freeQ, usedQ: QHdrPtr): OSErr
;
;
SL_InitSktListener PROC EXPORT
StackFrame RECORD {A6Link},DECR ; build a stack frame record
Result1 DS.W 1 ; function's result returned to caller
ParamBegin EQU * ; start parameters after this point
freeQ DS.L 1 ; freeQ parameter
usedQ DS.L 1 ; usedQ parameter
ParamSize EQU ParamBegin-* ; size of all the passed parameters
RetAddr DS.L 1 ; placeholder for return address
A6Link DS.L 1 ; placeholder for A6 link
LocalSize EQU * ; size of all the local variables
ENDR
WITH StackFrame,QHdr ; use these record types
LINK A6,#LocalSize ; allocate our local stack frame
; copy the queue header pointers into our local storage for use in the listener
LEA used_queue,A0 ; copy usedQ into used_queue
MOVE.L usedQ(A6),(A0)
LEA free_queue,A0 ; copy freeQ into free_queue
MOVE.L freeQ(A6),(A0)
; dequeue the first buffer record from freeQ and set current_qelem to it
MOVEA.L freeQ(A6),A1 ; A1 = ^freeQ
LEA current_qelem, A0 ; copy freeQ.qHead into current_qelem
MOVE.L qHead(A1),(A0)
MOVEA.L qHead(A1),A0 ; A0 = freeQ.qHead
_Dequeue
MOVE.W D0,Result1(A6) ; Return status
@1 UNLK A6 ; destroy the link
MOVEA.L (SP)+,A0 ; pull off the return address
ADDA.L #ParamSize,SP ; strip all of the caller's parameters
JMP (A0) ; return to the caller
ENDP
END ; end of this source file
Initializing the Socket Listener
To initialize the socket listener, define the free and used queue QHdr variables. You’ll need to define a PacketBuffer structure to match the record structure defined in the socket listener code. If you add any new fields, then you need to modify the PacketBuffer structure defined in the listener code. In the sample below, an array of 10 PacketBuffers is declared. Initialize the buffer packets, then queue them into the free queue using the _Enqueue trap. Call SL_InitSktListener and pass the addresses of the QHdr variable for the free and used queues. The following Pascal code demonstrates this process:
USES MEMTYPES, QUICKDRAW, OSINTF, APPLETALK;
CONST
ddpMaxData = 586;
TYPE
PacketBuffer = RECORD
qLink: QElemPtr;
qType: Integer;
buffer_Type: Integer;
buffer_NodeID: Integer;
buffer_Address: AddrBlock;
buffer_Hops: Integer;
buffer_ActCount: Integer;
buffer_CheckSum: OSErr;
buffer_Data: ARRAY[1..ddpMaxData] OF SignedByte;
END;
VAR
freeQ, usedQ: QHdr;
Buffers: ARRAY[1..10] OF PacketBuffer;
PROCEDURE SL_TheListener;
External;
FUNCTION SL_InitSktListener (freeQ, usedQ: QHdrPtr): OSErr;
External;
PROCEDURE SetUpSocketListener;
VAR
err: OSErr;
i: Integer;
BEGIN
freeQ.QHead := NIL; { initialize to nil to indicate empty queue }
freeQ.QTail := NIL; { initialize to nil to indicate end of queue }
usedQ.QHead := NIL; { initialize to nil to indicate empty queue }
usedQ.QTail := NIL; { initialize to nil to indicate end of queue }
FOR i := 1 TO 10 DO
Enqueue(@Buffers[i], @freeQ);
err := SL_InitSktListener(@freeQ, @usedQ);
IF err <> noErr THEN
BEGIN
{ Perform error processing here }
END;
END;
For C programmers, the initialization code is as follows:
#include <types.h>
#include <appletalk.h>
#include <OSUtils.h>
#include <stdio.h>
#define ddpMaxData 586
typedef struct {
QElemPtr qLink;
short qType;
short buffer_type; /* DDP Type */
short buffer_NodeID; /* Destination Node */
AddrBlock buffer_Address; /* Source Address in AddrBlock format */
short buffer_Hops; /* Hop count */
short buffer_ActCount; /* length of DDP datagram */
OSErr buffer_CheckSum; /* Checksum returned here */
char buffer_Data[ddpMaxData]; /* the DDP datagram */
freeQ.QHead = nil; /* initialize to nil to indicate empty queue */
freeQ.QTail = nil; /* initialize to nil to indicate end of queue */
usedQ.QHead = nil; /* initialize to nil to indicate empty queue */
usedQ.QTail = nil; /* initialize to nil to indicate end of queue */
for (i = 0; i < 10; i++)
Enqueue((QElemPtr)&buffers[i], &freeQ);
err = SL_INITSKTLISTENER (&freeQ, &usedQ);
if (err != noErr) {
/* perform error processing here */
}
}
Using the Socket Listener
The socket listener is set in use with the POpenSkt function, or with the more specific POpenATPSkt function. The program then periodically checks the usedQ.QHead value to determine whether the socket listener has processed a packet. If so, the packet is processed, Dequeued from the used queue, and Enqueued into the free queue. It’s also possible for the same socket listener to be used by separate processes in the program. If so, the program must scan the list for the desired packet(s). Note that if multiple packets are expected, it is possible that the program may process the first packet before the listener processes the second packet. The program needs to be designed to check the usedQ.QHead value later for the additional packets.
TYPE
PacketBuffer = RECORD
qLink: QElemPtr;
qType: Integer;
buffer_Type: Integer;
buffer_NodeID: Integer;
buffer_Address: AddrBlock;
buffer_Hops: Integer;
buffer_ActCount: Integer;
buffer_CheckSum: OSErr;
buffer_Data: ARRAY[1..ddpMaxData] OF SignedByte;
END;
PacketPtr = ^PacketBuffer;
VAR
freeQ, usedQ: QHdr;
bufPtr : PacketPtr;
.
.
.
WHILE (usedQ.QHead <> nil) DO { check if packet available for processing }
BEGIN
bufPtr := PacketPtr(usedQ.QHead); { get the packet ptr }
IF (Dequeue(QElemPtr(bufPtr), @usedQ) <> noErr) THEN
BEGIN
{ Process the packet information }
Enqueue(QElemPtr(bufPtr), @freeQ); { requeue the packet buffer for use. }
The AppleTalk Transition Queue keeps applications and other resident processes on the Macintosh informed of AppleTalk events, such as the opening and closing of AppleTalk drivers, or changes to the Flagship name (to be discussed later in this Note). A comprehensive discussion of the AppleTalk Transition Queue is presented in Inside Macintosh Volume VI, Chapter 32. New to the AppleTalk Transition Queue are messages regarding the Flagship Naming Service, the AppleTalk Multiple Node Architecture (also to be discussed later in this Note), changes to processor speed that may affect LocalTalk timers, and a transition to indicate change of the network cable range.
Later in this section is a sample Transition Queue procedure in both C and Pascal that includes the known transition selectors. There is also a sample Pascal source for determining whether the LAP Manager version 53 or later exists. Calling LAPAddATQ for AppleTalk versions 52 and earlier will result in a system crash since the LAP Manager is not implemented prior to AppleTalk version 53. The Boolean function, LAPMgrExists, should be used instead of checking the low-memory global LAPMgrPtr, $0B18.
Bug With LAPAddATQ and LAPRmvATQ Glue Code
A bug exists in the glue code for the LAPAddATQ and for the LAPRmvATQ routines in the Interface.o file. The same glue code is used with the Think C version 5.0.x product and will affect those users as well.
In the glue code, these calls use the Pascal stack calling convention by allocating memory on the stack for the OSErr result. The ATQEntryPtr is then pushed onto the stack and the LAP Manager is called. Upon return from a JSR instruction to the LAP Manager code, the return address is placed in register A0 and the stack incremented. The glue code should then move the 2-byte result onto the stack into the location reserved for the result. Instead, the glue code decrements the stack pointer by 2 bytes before moving the result onto the stack. The glue code jumps to the return address in register A0. Upon return, the stack is off by 2 bytes. If local variables are used and are referenced from the stack pointer in register A7, following the return from these LAP Manager calls, access to the local variables may not be correct.
The following Assembler glue code is supplied for MPW users to assemble and link with their programs. For the remainder of this Tech Note, the call LAPAddATQFix and LAPRmvATQFix will be used instead and refer to the following code. For Think C programmers, the same functions are presented using in-line Assembler. For Think Pascal programmers, one solution is to compile the Think C code and to link with the resulting Library file.
For Think C programmers, the following code sample can be used. Think Pascal programmers can link with the library file produced by compiling this code with the Think C compiler.
System software version 7.0 requires the use of the MPW version 3.2 interface files and libraries. The AppleTalk interface presents two new routines for calling all processes in the AppleTalk Transition Queue. Rather than use parameter block control calls as described in M.NW.AppleTalk2Mac, use the ATEvent procedure or the ATPreFlightEvent function to send transition notification to all queue elements. These procedures are discussed in Inside Macintosh Volume VI, Chapter 32.
Note: You can call the ATEvent and ATPreFlightEvent routines only at virtual memory safe time. See the Memory Management chapter of Inside Macintosh Volume VI, Chapter 28, for information on virtual memory.
Standard AppleTalk Transition Constants
Use the following constants for the standard AppleTalk transitions:
ATTransCableChange = 'rnge' {cable range change transition }
ATTransSpeedChange = 'sped' {change in cpu speed }
The following information concerns the new transitions from ATTransNetworkTransition through ATTransSpeedChange.
The Flagship Naming Service
System software version 7.0 allows the user to enter a personalized name by which her system will be published when connected to an AppleTalk network. The System 'STR ' resource ID –16413 is used to hold this name. The name (listed as Macintosh Name) can be up to 31 characters in length and can be set using the Sharing Setup Control Panel Device (cdev). This resource is different from the Chooser name, System 'STR ' resource ID –16096. When providing network services for a workstation, the Flagship name should be used so that the user can personalize his workstation name while maintaining the use of the Chooser name for server connection identification. It’s important to note that the Flagship name resource is available only from system software version 7.0. DTS recommends that applications not change either of these 'STR ' resources.
Applications taking advantage of this feature should place an entry in the AppleTalk Transition Queue to stay informed as to changes to this name. Three new transitions have been defined to communicate Flagship name changes between applications and other resident processes. Support for the Flagship Naming Service Transitions is provided starting from AppleTalk version 56. Note that AppleTalk version 56 can be installed on pre-7.0 systems; however, the Flagship Naming Service is available only from system software 7.0 and later.
The ATTransNameChangeAskTask Transition
From Assembly language, the stack upon calling looks as follows:
ATQEvent RECORD 0
ReturnAddr DS.L 1 ; address of caller
theEvent DS.L 1 ; = 7; ID of ATTransNameChangeAskTask transaction
aqe DS.L 1 ; pointer to task record
infoPtr DS.L 1 ; pointer to NameChangeInfo parameter block
ENDR
The NameChangeInfo record block is as follows
NameChangeInfoPtr: ^NameChangeInfo;
NameChangeInfo = RECORD
newObjStr: Str32; {new Flagship name to change to }
name: StringPtr; {ptr to location to place ptr to process }
{name }
END;
The ATTransChangeNameAskTask is issued under system software version 7.0 to inform Flagship clients that a process wants to change the Flagship name. Each AppleTalk Transition Queue element that processes the ATTransChangeNameAskTask can inspect the NameChangeInfoPtr^.newObjStr to determine the new Flagship name. If you deny the request, you must set the NameChangeInfoPtr^.name pointer with a pointer to a Pascal string buffer containing the name of your application or to the nil pointer. The AppleTalk Transition Queue process returns this pointer. The requesting application can display a dialog notifying the user of the name of the application that refused the change request.
While processing this event, you can make synchronous calls to the Name-Binding Protocol (NBP) to attempt to register your entity under the new name. It is recommended that you register an entity using the new Flagship name while handling the ATTransChangeNameAskTask event. You should not deregister an older entity at this point. Your routine must return a function result of 0 in the D0 register, indicating that it accepts the request to change the Flagship name, or a nonzero value, indicating that it denies the request.
Warning: DTS does not recommend that you change the Flagship name. The Sharing Setup cdev does not handle this event and the Macintosh name will not be updated to reflect this change if the cdev is open.
The ATTransNameChangeTellTask Transition
From Assembly language, the stack upon calling looks as follows:
ATQEvent RECORD 0
ReturnAddr DS.L 1 ; address of caller
theEvent DS.L 1 ; = 6; ID of ATTransNameChangeTellTask transaction
aqe DS.L 1 ; pointer to task record
infoPtr DS.L 1 ; pointer to the new Flagship name
ENDR
A process uses ATEvent to send the ATTransNameChangeTellTask to notify AppleTalk Transition Queue clients that the Flagship name is being changed. The LAP Manager then calls every routine in the AppleTalk Transition Queue that the Flagship name is being changed.
When the AppleTalk Manager calls your routine with a ATTransNameChangeTellTask transition, the third item on the stack is a pointer to a Pascal string of the new Flagship name to be registered. Your process should deregister any entities under the old Flagship name at this time. You can make synchronous calls to NBP to deregister an entity. Return a result of 0 in the D0 register.
Note: When the AppleTalk Manager calls your process with a TellTask transition (that is, with a routine selector of ATTransNameChangeTellTask), you cannot prevent the Flagship name from being changed.
To send notification that your process intends to change the Flagship name, use the ATEvent function described above. Pass ATTransNameChangeTellTask as the event parameter and a pointer to the new Flagship name (Pascal string) as the infoPtr parameter.
The ATTransCancelNameChange Transition
From Assembly language, the stack upon calling looks as follows:
ATQEvent RECORD 0
ReturnAddr DS.L 1 ; address of caller
theEvent DS.L 1 ; = 8; ID of ATTransCancelNameChange transaction
aqe DS.L 1 ; pointer to task record
ENDR
The ATTransCancelNameChange transition complements the ATTransNameChange-AskTask transition. Processes that acknowledged an ATTransNameChangeAskTask transition will be sent the ATTransCancelNameChange transition if a later process disallows the change of Flagship name. Your process should deregister any NBP entities registered during the ATTransNameChangeAskTask transition. You can make synchronous calls to NBP to deregister an entity. Return a result of 0 in the D0 register.
System 7.0 Sharing Setup cdev / Flagship Naming Service Interaction
The Flagship Naming Service is a new system service built into System 7. It is used to publish the workstation using the Flagship name. The Flagship Naming Service implements an AppleTalk Transition Queue element to respond to changes in the Flagship name. For example, the Sharing Setup cdev can be used to reset the Flagship name. When a new Macintosh (Flagship) name is entered in Sharing Setup, Sharing Setup sends an ATTransNameChangeAskTask message to the AppleTalk Transition Queue to request permission to change the Flagship name. The Flagship Naming Service receives the ATTransNameChangeAskTask transition and registers the new name under the type “Workstation” on the local network. Sharing Setup follows with the ATTransNameChangeTellTask to notify AppleTalk Transition Queue clients that a change in Flagship name will occur. The Flagship Naming Service responds by deregistering the workstation under the old Flagship name.
If an error occurs from the NBPRegister call, Flagship Naming Service returns a nonzero error (the error returned from NBPRegister) and a pointer to its name in the NameChangeInfoPtr^.Name field. Note that the Workstation name is still registered under the previous Flagship name at this point.
AppleTalk Remote Access Network Transition Event
AppleTalk Remote Access allows you to establish an AppleTalk connection between two Macintosh computers over standard telephone lines. If the Macintosh you dial-in to is on an AppleTalk network, such as LocalTalk or Ethernet, your Macintosh becomes, effectively, a node on that network. You are then able to use all the services on the new network. Given this new capability, it is important that services running on your Macintosh be notified when new AppleTalk connections are established and broken. For this reason, the ATTransNetworkTransition event has been added to AppleTalk version 57. With version 57 present, this event can be expected in system software version 6.0.5 or later.
Internally, both the AppleTalk Session Protocol (ASP) and the AppleTalk Data Stream Protocol (ADSP) have been modified to respond to this transition event. When a disconnect transition event is detected, these drivers close down sessions on the remote side of the connection.
The ATTransNetworkTransition Transition
From Assembly language, the stack upon calling looks as follows:
ATQEvent RECORD 0
ReturnAddr DS.L 1 ; address of caller
theEvent DS.L 1 ; = 5; ID of ATTransNetworkTransition
aqe DS.L 1 ; pointer to task record
infoPtr DS.L 1 ; pointer to the TNetworkTransition record
ENDR
The TNetworkTransition record block is passed as follows:
TNetworkTransition RECORD 0
private DS.L 1 ; pointer used internally by AppleTalk Remote Access
netValidProc DS.L 1 ; pointer to the network validate procedure
newConnectivity DS.B 1 ; true = new connectivity, false = loss of connectivity
ENDR
Network Transition Event for AppleTalk Remote Access
Network Transition events are generated by AppleTalk Remote Access to inform AppleTalk Transition Queue applications and resident processes that network connectivity has changed. The type of change is indicated by the NetTransPtr^.newConnectivity flag. If this flag is true, a connection to a new internet has taken place. In this case, all network addresses will be returned as reachable. If the newConnectivity flag is false, certain networks are no longer reachable. Since AppleTalk Remote Access is connection based, it has knowledge of where a specific network exists. AppleTalk Remote Access can take advantage of that knowledge during a disconnect to inform AppleTalk Transition Queue clients that a network is no longer reachable. This information can be used by clients to age out connections immediately rather than waiting a potentially long period of time before discovering that the other end is no longer responding.
When AppleTalk Remote Access is disconnecting, it passes a network validation hook in the TNetworkTransition record, NetTransPtr^.netValidProc. A client can use the validation hook to ask AppleTalk Remote Access whether a specific network is still reachable. If the network is still reachable, the validate function will return true. A client can then continue to check other networks of interest until the status of each one has been determined. After a client has finished checking networks, control returns to AppleTalk Remote Access where the next AppleTalk Transition Queue client is called.
The information the network validation hook returns is valid only if a client has just been called as a result of a transition. A client can validate networks only when she has been called to handle a Network Transition event. Note that the Network Transition event can be called as the result of an interrupt, so a client should obey all of the normal conventions involved with being called at this time (for example, don’t make calls that move memory and don’t make synchronous Preferred AppleTalk calls).
To check a network number for validity the client uses the network validate procedure to call AppleTalk Remote Access. This call is defined using C calling conventions as follows:
pascal long netValidProc(TNetworkTransition *thetrans, unsigned long theAddress);
thetrans --> Pass in the TNetworkTransition record given to you when your transition handler was called.
theAddress --> This is the network address you want checked. The format of theAddress is the same as AddrBlock as defined in Inside Macintosh II, page 281:
Bytes 2 & 3 (High Word) - Network Number
Byte 1 - Node Number
Byte 0 (Low Byte) - Socket Number
Result codes true network is still reachable
false network is no longer reachable
AppleTalk Transition Queue handlers written in Pascal must implement glue code to use the netValidProc.
Cable Range Change Transition Event
The Cable Range Transition, ATTransCableChange, event informs AppleTalk Transition Queue processes that the cable range for the current network has changed. This can occur when a router is first seen, when the last router ages out, or when an RTMP broadcast packet is first received with a cable range that is different from the current range. The ATTransCableChange event is implemented beginning with AppleTalk version 57. Most applications should not need to process this event. With version 57 present, this event can be expected in system software version 6.0.5 and later.
The ATTransCableChange Transition
From Assembly language, the stack upon calling looks as follows:
ATQEvent RECORD 0
ReturnAddr DS.L 1 ; address of caller
theEvent DS.L 1 ; = 'rnge'; ID of ATTransCableChange
aqe DS.L 1 ; pointer to task record
infoPtr DS.L 1 ; pointer to the TNetworkTransition record
ENDR
The TNewCRTrans record block is passed as follows:
TNewCRTrans RECORD 0
newCableLo DS.W 1 ; the new Cable Lo received from RTMP
newCableHi DS.W 1 ; the new Cable Hi received from RTMP
ENDR
The cable range is a range of network numbers starting from the lowest network number through the highest network number defined by a seed router for a network. All node addresses acquired on a network must have a network number within the defined cable range. For nonextended networks, the lowest and the highest network numbers are the same. If the cable range on the network changes, for example, if the router on the network goes down, the Cable Range Change event will be issued with the parameters described earlier in this Technical Note.
After receiving the event, a multinode application should use the new cable range to check if all the multinodes it obtained prior to the event are still valid. For the invalid multinodes, the application should issue the .MPP RemoveNode control call to get rid of invalid nodes. The .MPP AddNode control call can be issued immediately after removing invalid nodes to obtain new valid multinodes in the new cable range. This Cable Range Change Transition event will be issued only during system task time.
The Speed Change Transition Event
The ATTransSpeedChange Transition event is defined for applications that change CPU speed without rebooting, to notify time-dependent processes that such change has taken place. Such speed change occurs when altering the cache states on the 68030 or 68040 CPUs, or with third- party accelerator cards that allow speed changes on the fly via a cdev. Any process that alters the effective CPU speed should use the ATEvent to notify processes of this change. Issue the ATTransSpeedChange event only at SystemTask time! Any process that depends on changes to the CPU speed should watch for this event. The Speed Change Transition event is issued only during system task time.
One time-dependent code module is LocalTalk, whose low-level timer values must be recalculated when the CPU speed changes. Note that altering the cache state on the 68030 does not affect LocalTalk; however doing so on the 68040 does affect LocalTalk timers. This event must be sent by any application that toggles caching on the 68040 processor on the fly. If the cache is toggled and LocalTalk is not notified, a loss of network connection will result if LocalTalk is the current network connection. Note that only LocalTalk implemented in AppleTalk version 57 or later recognizes the Speed Change Transition event. Contact Apple Software Licensing for licensing AppleTalk version 57.
Regarding LocalTalk on the Macintosh Plus, the timing values are hard-coded in ROM regardless of the CPU speed. Vendors of accelerators for Macintosh Plus computers should contact DTS for information on how to make LocalTalk work for you.
The ATTransSpeedChange Transition
From Assembly language, the stack upon calling looks as follows:
ATQEvent RECORD 0
ReturnAddr DS.L 1 ; address of caller
theEvent DS.L 1 ; = 'sped'; ID of ATTransSpeedChange
aqe DS.L 1 ; pointer to task record
ENDR
To notify LocalTalk that a change in processor speed has taken place, use the ATEvent procedure. Pass ATTransSpeedChange as the event parameter and a nil pointer as the infoPtr parameter. This event must be issued only at system task time. The ATEvent procedure is implemented as a glue routine in MPW 3.2 or greater. The following line of code demonstrates notification of the ATTransSpeedChange event.
ATEvent (ATTransSpeedChange, nil);
Sample Pascal Source to LAPMgrExists Function
It is important to check whether the LAP Manager exists before making LAP Manager calls like LAPAddATQ. The LAP Manager is implemented beginning with AppleTalk version 53. Rather than check the low-memory global LAPMgrPtr, it is preferable to check for its existence from a higher level. The following Pascal source demonstrates this technique:
FUNCTION GestaltAvailable: Boolean;
CONST
_Gestalt = $A1AD;
BEGIN
GestaltAvailable := TrapAvailable(_Gestalt);
{ TrapAvailable is documented in Inside Macintosh Volume VI, page 3-8 }
END;
FUNCTION AppleTalkVersion: Integer;
CONST
versionRequested = 1; { version of SysEnvRec }
VAR
refNum: INTEGER;
world: SysEnvRec;
attrib: LONGINT;
BEGIN
AppleTalkVersion := 0; { default to no AppleTalk }
IF OpenDriver('.MPP', refNum) = noErr THEN { open the AppleTalk driver }
IF GestaltAvailable THEN
BEGIN
IF (Gestalt(gestaltAppleTalkVersion, attrib) = noErr) THEN
AppleTalkVersion := BAND(attrib, $000000FF);
END
ELSE { Gestalt or gestaltAppleTalkVersion selector isn't available. }
IF SysEnvirons(versionRequested, world) = noErr THEN
AppleTalkVersion := world.atDrvrVersNum;
END;
FUNCTION LAPMgrExists: Boolean;
BEGIN
{ AppleTalk phase 2 is in AppleTalk version 53 and later }
LAPMgrExists := (AppleTalkVersion >= 53);
END;
Sample AppleTalk Transition Queue Function
A sample AppleTalk Transition Queue function has been implemented in both C and Pascal. These samples have been submitted as snippet code to appear on the Developer CD Series disc. Since Transition Queue handlers are called with a C-style stack frame, the Pascal sample includes the necessary C glue.
Sample AppleTalk Transition Queue Function in C
The following is a sample AppleTalk Transition Queue handler for C programmers. To place the handler in the AppleTalk Transition Queue, define a structure of type myATQEntry in the main body of the application. Assign the SampleTransQueue function to the myATQEntry.CallAddr field. Use the LAPAddATQFixed function to add the handler to the AppleTalk Transition Queue. Remember to remove the handler with the LAPRmvATQFixed function before quitting the application.
Warning: The System 7 Tuner extension will not load AppleTalk resources if it detects that AppleTalk is off at boot time. Remember to check the result from the LAPAddATQFixed function to determine whether the handler was installed successfully.
long SampleTransQueue(long selector, myATQEntry *q, void *p)
{
long returnVal = 0; /* return 0 for unrecognized events */
NameChangePtr myNameChangePtr;
TNewCRTransPtr myTNewCRTransPtr;
TNetworkTransitionPtr myTNetworkTransitionPtr;
NetworkTransitionProcPtr myNTProcPtr;
StringPtr newNamePtr;
long checkThisNet;
char **t;
short myCableLo, myCableHi;
/*
* This is the dispatch part of the routine. We'll check the selector passed into the task; its location is 4 bytes off the stack (selector).
*/
switch(selector) {
case ATTransOpen:
/*
* Someone has opened the .MPP driver. This is where one would * reset the application to its usual network state (that is, * you could register your NBP name here). Always return 0.
*/
break;
case ATTransClose:
/*
* When this routine is called, .MPP is going to shut down no * matter what we do. Handle that type of situation here (that * is, one could remove an NBP name and close down all * sessions); 'p' will be nil. Return 0 to indicate no error.
*/
break;
case ATTransClosePrep:
/*
* This event gives us the chance to deny the closing of * AppleTalk if we want. Returning a value of 0 means it's OK * to close; nonzero indicates we'd rather not close at this * time.
*
* With this event, the parameter 'p' actually means * something. 'p' in this event is a pointer to an address * that can hold a pointer to a string of our choosing. This * string indicates to the user which task would rather not * close. If you don't want AppleTalk to close, but you don't * have a name to stick in there, you MUST place a nil value * in there instead.
*
* (We're doing this all locally to this case because it's C * and we can, so there.)
*/
newNamePtr = (StringPtr)NewPtr(sizeof(Str32));
/*
* Assume Ptr allocation successful.
*/
newNamePtr = "\pBanana Mail"; /* This will either be an Ax reference or PC relative depending on compiler and options. */
/*
* Get a new reference to the address we were passed (in a * form we can use).
*/
t = (char **) p;
/*
* Place the address of our string into the address we were * passed.
*/
*t = (char *)newNamePtr;
/*
* Return a nonzero value so that AppleTalk knows we'd rather * not close.
*/
returnVal = 1;
break;
case ATTransCancelClose:
/*
* Just kidding, we didn't really want to cancel that * AppleTalk closing after all. Reset all your network * activities that you have disabled here (if any). In our * case, we'll just fall through. 'p' will be nil.
*/
break;
case ATTransNetworkTransition:
/*
* A Remote AppleTalk connection has been made or broken.
* 'p' is a pointer to a TNetworkTransition record.
if ((*myNTProcPtr)(myTNetworkTransitionPtr, checkThisNet)) {
/*
* Network is still valid.
*/
}
else {
/*
* Network is no longer valid.
*/
}
}
break;
case ATTransNameChangeTellTask:
/*
* Someone is changing the Flagship name and there is nothing * we can do. The parameter 'p' is a pointer to a Pascal-style * string that holds the new Flagship name. */
newNamePtr = (StringPtr) p;
/*
* You should deregister any previously registered NBP entries * under the 'old' Flagship name. Always return 0.*/
break;
case ATTransNameChangeAskTask:
/*
* Someone is messing with the Flagship name.
* With this event, the parameter 'p' actually means * something. 'p' is a pointer to a NameChangeInfo record. The * newObjStr field contains the new Flagship name. Try to * register a new entity using the new Flagship name. * Returning a value of 0 means it's OK to change the Flagship * name.
*/
myNameChangePtr = (NameChangePtr)p;
/*
* If the NBPRegister is unsuccessful, return the error. You * must also set p->name pointer with a pointer to a Pascal- * style string of the process name. */
break;
case ATTransCancelNameChange:
/*
* Just kidding, we didn't really want to change that name * after all. Remove new NBP entry registered under the * ATTransNameChangeAskTask Transition. In our case, we'll * just fall through. 'p' will be nil. Remember to return 0. */
break;
case ATTransCableChange:
/*
* The cable range for the network has changed. The pointer * 'p' points to a structure with the new network range. * (TNewCRTransPtr)p->newCableLo the lowest value of the new * network range. (TNewCRTransPtr)p->newCableHi is the highest * value of the new network range. After handling this event, * always return 0. */
myTNewCRTransPtr = (TNewCRTransPtr)p;
myCableLo = myTNewCRTransPtr->newCableLo;
myCableHi = myTNewCRTransPtr->newCableHi;
break;
case ATTransSpeedChange:
/*
* The processor speed has changed. Only LocalTalk responds to * this event. We demonstrate this event for completeness * only. Always return 0. */
break;
default:
/*
* For future Transition Queue events (and yes, Virginia, * there will be more). */
break;
} /* end of switch */
/*
* return value in register D0
*/
return returnVal;
}
Sample AppleTalk Transition Queue Function in Pascal
The following is a sample AppleTalk Transition Queue handler for Pascal programmers. AppleTalk Transition Queue handlers are passed parameters using the C parameter passing convention. In addition, the 4-byte function result must be returned in register D0. To meet this requirement, a C procedure is used to call the handler, then to place the 4-byte result into register D0. The stub procedure listing follows the handler.
To place the handler in the AppleTalk Transition Queue, define a structure of type myATQEntry in the main body of the application. Assign the CallTransQueue C procedure to the myATQEntry.CallAddr field. Use the LAPAddATQFixed function to add the handler to the AppleTalk Transition Queue. Remember to remove the handler with the LAPRmvATQFixed function before quitting the application.
Warning: The System 7 Tuner extension will not load AppleTalk resources if it detects that AppleTalk is off at boot time. Remember to check the result from the LAPAddATQFixed function to determine whether the handler was installed successfully.
The following code was written with MPW Pascal and C v3.2:
FUNCTION SampleTransQueue (selector :LONGINT; q :myATQEntryPtr; p :Ptr) : LONGINT;
{
* Transition Queue routines are designed with C calling conventions in mind.
* They are passed parameters with a C-style stack and return values are expected
* to be in register D0. Note that the CallTransQueue C glue routine is used
* to reverse the C-style stack to Pascal style before calling the handler. The
* procedure CallTransQueue follows this listing. To install this Trans Queue
* handler, assign CallTransQueue to the CallAddr field, NOT SampleTransQueue.
}
FUNCTION CallNetValidProc(p : ProcPtr; netTrans : TNetworkTransitionPtr;
theNet : LONGINT) : LONGINT;
{
* CallNetValidProc is used to call the netValidProc passed in the
* TNetworkTransition record. Since Pascal cannot call the ProcPtr directly, a C
* glue routine is used. This routine is defined following this listing.
}
IMPLEMENTATION
FUNCTION SampleTransQueue (selector :LONGINT; q :myATQEntryPtr; p :Ptr) : LONGINT;
VAR
returnVal : LONGINT;
myNameChgPtr : NameChangePtr;
myTNewCRTransPtr : TNewCRTransPtr;
myTNetworkTransitionPtr : TNetworkTransitionPtr;
newNamePtr : StringPtr;
processNameHdl : StringHandle;
myCableLo, myCableHi : INTEGER;
shortSelector : INTEGER;
checkThisNet
BEGIN
returnVal := 0; { return 0 for unrecognized events )
{
* This is the dispatch part of the routine. We'll check the selector passed * into the task; its location is 4 bytes off the stack (selector).
}
IF ((selector <= ATTransCancelNameChange) AND (selector >= ATTransOpen)) THEN
{
* Check whether a numeric selector is being used whose known values are * between 8 and 0 so that we can implement a CASE statement with an INTEGER * var.
}
BEGIN
shortSelector := selector;
CASE shortSelector OF
ATTransOpen:
BEGIN
{
* Someone has opened the .MPP driver. This is where * one would reset the application to its usual * network state (that is, you could register your NBP * name here). Always return 0.
}
END;
ATTransClose:
BEGIN
{
* When this routine is called, .MPP is going to shut * down no matter what we do. Handle that type of * situation here (that is, one could remove an NBP * name and close down all sessions). 'p' will be nil. * Return 0 to indicate no error.
}
END;
ATTransClosePrep:
BEGIN
{
* This event gives us the chance to deny the closing * of AppleTalk IF we want. Returning a value of 0 * means it's OK to close; nonzero indicates we'd * rather not close at this time.*
* With this event, the parameter 'p' actually means * something. 'p' in this event is a pointer to an * address that can hold a pointer to a string of our * choosing. This string indicates to the user which * task would rather not close. If you don't want * AppleTalk to close, but you don't have a name to * stick in there, you MUST place a nil value in * there instead.
}
{
* Get a new reference to the address we were passed * (in a form we can use).
* (We're doing this all locally to this case because * we can, so there.)
* Place the address of our string into the address we * were passed.
}
:= 'Banana Mail';
Ptr(p) := Ptr(processNameHdl);
{
* Return a nonzero value so that AppleTalk knows we'd * rather not close.
}
returnVal := 1;
END;
ATTransCancelClose:
BEGIN
{
* Just kidding, we didn't really want to cancel that * AppleTalk closing after all. Reset all your network * activities that you have disabled here (IF any). In * our case, we'll just fall through. 'p' will be nil.
}
END;
ATTransNetworkTransition:
BEGIN
{
* A Remote AppleTalk connection has been made or * broken. 'p' is a pointer to a TNetworkTransition * record. Always return 0.
if (CallNetValidProc(myTNetworkTransitionPtr^.netValidProc,
myTNetworkTransitionPtr, checkThisNet) <> 0) THEN
BEGIN
{
* Network is still valid.
}
END
ELSE
BEGIN
{
* Network is no longer valid.
}
END;
END;
END;
ATTransNameChangeTellTask:
BEGIN
{
* Someone is changing the Flagship name and there is * nothing we can do. The parameter 'p' is a pointer * to a Pascal-style string that holds the new * Flagship name.
}
newNamePtr := StringPtr (p);
{
* You should deregister any previously registered NBP * entries under the 'old' Flagship name. Always * return 0.
}
END;
ATTransNameChangeAskTask:
BEGIN
{
* Someone is messing with the Flagship name.
* With this event, the parameter 'p' actually means * something. 'p' is a pointer to a NameChangeInfo * record. The newObjStr field contains the new * Flagship name. Try to register a new entity using * the new Flagship name. Returning a value of 0 means * it's OK to change the Flagship name.
}
myNameChgPtr := NameChangePtr (p);
{
* If the NBPRegister is unsuccessful, return the * error. You must also set p->name pointer with a * pointer to a string of the process name.
}
END;
ATTransCancelNameChange:
BEGIN
{
* Just kidding, we didn't really want to cancel that * name change after all. Remove new NBP entry * registered under the ATTransNameChangeAskTask * Transition. 'p' will be nil. Remember to return 0.
}
END;
OTHERWISE
returnVal := 0;
{
* Just in case some other numeric selector is * implemented.
}
END; { CASE }
END
ELSE IF (ResType(selector) = ATTransCableChange) THEN
BEGIN
{
* The cable range for the network has changed. The pointer 'p' * points to a structure with the new network range. * (TNewCRTransPtr)p->newCableLo is the lowest value of the new * network range. (TNewCRTransPtr)p->newCableHi is the highest value * of the new network range. After handling this event, always return * 0.
}
myTNewCRTransPtr := TNewCRTransPtr(p);
myCableLo := myTNewCRTransPtr^.newCableLo;
myCableHi := myTNewCRTransPtr^.newCableHi;
returnVal := 0;
END
ELSE IF (ResType(selector) = ATTransSpeedChange) THEN
BEGIN
{
* The processor speed has changed. Only LocalTalk responds to this * event. We demonstrate this event for completeness only. Always * return 0.
}
returnVal := 0;
END; { IF }
SampleTransQueue := returnVal;
END;
FUNCTION CallNetValidProc(p : ProcPtr; netTrans : TNetworkTransitionPtr;
pascal long SampleTransQueue (long selector, myATQEntry *q, void *p);
long CALLTRANSQUEUE(long selector, myATQEntry *q, void *p);
/* Capitalize CALLTRANSQUEUE so that linker can match this entry with */
/* the Pascal call. */
pascal long CallNetValidProc(ProcPtr p, TNetworkTransitionPtr netTrans, long theNet);
long CALLTRANSQUEUE(long selector, myATQEntry *q, void *p)
/* CallTransQueue sets up the Pascal stack for the SampleTransQueue handler, */
/* then puts the result into D0. */
{
return(SampleTransQueue(selector, q, p));
}
pascal long CallNetValidProc(ProcPtr p, TNetworkTransitionPtr netTrans, long theNet)
/* CallNetValidProc is used to call the netValidProc pointed to by ProcPtr p. */
{
NetworkTransitionProcPtr myNTProcPtr;
myNTProcPtr = (NetworkTransitionProcPtr)p;
return ((*myNTProcPtr)(netTrans, theNet));
}
Multivendor ADEV Architecture
With the release of AppleTalk version 56, Apple implemented the Multivendor ADEV Architecture. Under the original architecture with versions of AppleTalk prior to 56, using EtherTalk or TokenTalk on Macintosh II class machines permitted only one brand of NuBus card where multiple Ethernet or token ring connections were desired. Furthermore, there was no support for a configuration of a NuBus slot device and a “slotless” device, such as a SCSI Ethernet connection.
As Ethernet comes built in on next-generation CPUs, this clearly presents a problem for customers wishing to mix Ethernet controller brands on the same CPU. The Multivendor Architecture presents a common interface through which basic AppleTalk services are provided. The new architecture simplifies software development whereas AppleTalk engineering provides the ADEV file, and the developer provides the hardware level driver software for Ethernet and token ring. By following the new architecture, Ethernet and token ring hardware cards will be compatible as new services are provided by AppleTalk (for example, AppleTalk Remote Access and MacTCP).
AppleTalk version 56 and later is compatible with system software version 6.0.5 unless specifically stated otherwise in the release notes.
Original Limitations
The original product allowed only one type of NuBus Ethernet or token ring controller or one “slotless” controller. This Multivendor ADEV Architecture deals only with the restriction of differing NuBus controllers. It does not address the mutual exclusion of slot and slotless devices, nor does it address the singularity of slotless devices.
NuBus slot Ethernet or token ring controller hardware is recognized by the original product through a series of Slot Manager SNextTypesRsrc calls. Any NuBus device that is in the network category and has a type classification of Ethernet /token ring is considered a NuBus slot controller device. Whenever such a device is found in a NuBus slot, the user can select it as the current AppleTalk network connection, or it can be used as a port in an Internet Router configuration.
When the AppleTalk network system uses this connection, an _Open, IMMED trap call is made with an ioNamePtr -> “.ENET/.TOKN”, and the ioSlot field set to the slot containing the card. Since only one driver resource can be installed in the system with this name, only one type of Ethernet or token ring card was supported under the original architecture.
ENET Driver Shell
System software version 7.0 and later (and Network Software Installers (NSI) system software version 1.1 and later) is packaged with the .ENET driver shell that will support multiple NuBus Ethernet controllers. The sole function of this driver is to locate the appropriate driver resource for the particular device selected, and transfer control to the open routine for that driver. It accomplishes this in the following fashion:
• Obtains the Board ID from the board sResource information for the given slot.
• For the driver shell installed using NSI version 1.2.4 or later, the shell searches for resources of type 'enet' with the ID equal to the Board ID in the System file and in the System ROM, and for a driver in the slot resources in the ROM of the slot device. It uses the word (2 bytes) immediately following the DRVR name to determine which driver is the most recent; higher values are newer versions. If no driver is found, an open error is returned.
For the driver shell installed prior to NSI version 1.2.4, the shell uses _GetResource to obtain a resource of type 'enet' with the ID equal to the Board ID from the system file. If the resource is present, proceeds to use it as the driver code resource as defined below, otherwise attempts to load the driver from the slot resources in the ROM of the slot device. If neither code resource is found, returns an open error.
• Detaches the newly loaded resource.
• Modifies the device control entry for the current _Open call with information from the loaded driver code (address to the driver).
• Obtains the address of the open routine from the driver header information.
• JSRs to the open routine of the loaded driver.
• If the open is successful, returns, otherwise recovers the handle for the loaded driver and disposes of it.
This very simple technique allows developers to quickly repackage driver resources by simply changing the resource type and ID.
Built-in Ethernet on newer CPUs makes use of the board sResource list for slot zero, which should be present on all CPUs. These systems also have the Ethernet device sResource lists, and also have the .ENET driver in the sResources as well.
The Easy Install process supplied on the Network Software Installer version 1.1 and later, and on the system software installers for 7.0 and later, install the driver shell when it recognizes that an Apple EtherTalk NB or Ethernet NB (or other Ethernet board with Board ID 8) is installed in the system.
.TOKN Driver Shell
The .TOKN driver shell is currently available from Apple Software Licensing (SW.LICENSE) for licensing. The driver and Multivendor TokenTalk ADEV are being packaged beginning with system software version 7.0.1 and AppleTalk products that require AppleTalk version 57 or later. The operation of the .TOKN driver shell is similar to the .ENET driver shell. In place of searching for and loading the 'enet' resource, a 'tokn' resource will be used instead. The new driver will affect all developers whose .TOKN drivers get replaced by the driver shell.
.TOKN Driver Basics
The following guidelines describe the minimum requirements for developers of token ring products for the Macintosh to be compatible with the TokenTalk Phase 2 driver software. MacDTS strongly recommends that all developers of token ring products implement the basic functionality described below. By following these guidelines, the product will be compatible with AppleTalk Remote Access, MacTCP, and future releases of AppleTalk and related products.
The .TOKN driver is similar to the structure of the .ENET driver as described in Appendix B, “Macintosh Ethernet Driver Details” in the Macintosh AppleTalk Connections Programmer’s Guide (Final Draft 2, November 11, 1989) and more recently in Inside Macintosh Volume VI, page 32-88. These documents describe the expected functionality of the .ENET driver. The .TOKN driver interface that you design can be a superset of the functionality discussed here. The following are some additional guidelines and exceptions to consider:
• The driver can obtain the slot number from the DCE entry dCtlSlot.
• The driver need only support EAttach protocol type 0. Return an error on other protocol types.
• Implement the add and delete functional address in place of the EAddMulti and EDelMulti commands.
• Implement the ESetGeneral call to return a result of noErr.
• Implement source routing support if the driver is to support the source routing bridges.
• On EWrite call:
The first buffer in the WDS contains a 802.3 MAC header (6-byte destination address + 6-byte source address + 2-byte length field). The 6-byte destination address is the only important field to the driver. The source address and the length fields are not used for token ring media. The header is 14 bytes in length.
The second buffer in the WDS contains the LLC header and the SNAP header. This buffer is 8 bytes in length.
The remainder of the WDS is the user data.
The packet that gets put out on the “wire” will not include the 2-byte length field. The packet header will have the 6-byte destination address, followed by the 6-byte source address, followed by the LLC and SNAP header, and the user data.
• On Receive:
Define a Read Header Area (RHA) into which to create the 14 byte 802.3 MAC header. Read the header into the RHA and set A3 to point to the end of the RHA; place the 6-byte destination and source addresses into the first 12 bytes of the RHA. From the hardware, get the length of the packet and place it into the last 2 bytes of the RHA. This step is necessary as the LAP Manager is designed to handle and Ethernet style packet.
Calculate the packet length (LLC header + SNAP header + data). Place the length in register D1.W. Also place the computed length into the length field of the 802.3 MAC header (this length does not include the source routing and 802.5 fields). Place the address of the ReadPacket routine into register A4. Disable the interrupt. Call the protocol handler or use DeferUserFn as described below. Enable the interrupt.
As A0 is reserved for use by the driver, it could be used to point to the next byte to be read by the driver, for the ReadPacket and ReadRest functions.
• Other Notes:
If the protocol handler calls your ReadRest routine with a buffer too small to hold the entire remaining packet, set the Z-bit in the CCR before returning. Clearing the Z-bit indicates that the ReadRest routine handled the packet successfully.
Driver Considerations for Virtual Memory
With the release of system software version 7.0 and the virtual memory option, it is critical for driver software to protect against the possibility of a double page fault. Since driver software runs at interrupt time, a non-virtual memory compatible packet processing routine could cause a page fault while the Macintosh is already processing a page fault. To protect against this possibility, the DeferUserFn is provided to allow interrupt service routines to defer code, which might cause a page fault, until a safe time. The following guidelines will help make your driver code compatible with virtual memory.
• In the Open routine, use Gestalt to test for the presence of virtual memory, and whether it’s on. If so, set a flag in your dctlstorage that you can reference later.
• If virtual memory is enabled, always use DeferUserFn to defer the delivery of your packet data to your clients. This is necessary to protect against page faults at interrupt time when your client reads data into her own (probably unlocked) memory. In addition, do not touch any memory that is not locked down (in the virtual memory sense, not the Memory Manager sense) while processing your interrupts.
• Set the VMImmuneBit to keep the system from locking down memory (bit 0 at offset dCtlFlags + 1). If the VMImmuneBit isn’t set, the system locks the user’s parameter block. In contrast, the user’s buffers remain unlocked unless locked by the application. As a result, it is necessary to assume that the buffers are unlocked, and to use DeferUserFn accordingly. Having the system lock the parameter block results in a noticeable performance hit. The solution to this problem is to set the VMImmuneBit, and to be careful to “touch” the parameter block only when it is “safe” to do so. One time when it might be “unsafe” is in a completion routine. Therefore, use DeferUserFn .
The VMImmune bit is not currently found in the MPW headers. Add the following line somewhere at the beginning of your driver code:
VMImmuneBit EQU 0
Somewhere in the beginning of your code, assuming that the driver is now virtual memory-aware, add the following line:
BSET #VMImmuneBit,dCtlFlags+1(A1) ; set the bit
Warning: Do not assume that DeferUserFn will always successfully queue your packet-handling routine. Check the return result. Under specific situations, the Defer-Function Queue can become full. If the return result is cannotDeferErr exit the slot interrupt routine with a result of zero to indicate that the interrupt could not be serviced.
Limiting DeferUserFn Calls
Your interrupt service routine can reduce the number of calls to DeferUserFn depending on the Network Interface Controller (NIC) being used. With the SONIC and other NICs, incoming packets are queued. An ISR for such a NIC can be designed to process not only the packet that generated the interrupt, but also successive packets. As a result, the ISR can be designed to set a “deferred function” flag to indicate that the service routine has been queued, then process all packets that it finds in the card’s queue. When the service routine has completed, it can then reset the deferred function flag. If the ISR is reentered, it can check whether the deferred function flag is set. If so, simply exit with a nonzero result in register D0 to indicate that the packet was processed.
Using this algorithm, it is important to reset the NIC’s interrupt service register each time the ISR determines that a packet will be processed by a previously deferred function. If the register is not cleared, the card will remain in a constant state of interrupt, and the deferred function will never get a chance to execute.
Implementing DeferUserFn
The question may arise as to where to implement the DeferUserFn The following approach is one possible suggestion for devices that are not able to empty the NIC’s packet RAM all at once, and which implement a circular buffer or linked buffer list. Define an entry point where the ISR begins processing the packet from the card. At this entry point, there may be some code to check whether a packet transmission is under way and to perform a cleanup. There may also be code here to check whether the buffer has become overrun and to reset the NIC according to manufacturer’s guidelines. The driver code would copy the header into the RHA (Read Header Area), identify the protocol handler and set up register A4 with a pointer to the ReadPacket routine, then call the handler. Upon completion, the ISR might check whether additional packets have been received, if applicable. A flowchart of the deferred function process is as follows:
myDeferedFunction()
{
If transmit complete
do final cleanup of packet transmission
If buffer overrun
Reset the NIC according to manufacturer's guidelines
while(received packets are waiting in adapter ram)
{
process packet
call protocol handler
}
}
On entry to the ISR, see whether virtual memory is active by checking the flag set by the open routine. Perform whatever processing is necessary, then pass DeferUserFn, the entry point described above, if virtual memory is active. If virtual memory is inactive, branch to the entry point and process the packet.
With the introduction of SONIC-based Ethernet controllers, a modification was implemented into the Ethernet driver software to return additional information available from the SONIC chip network statistics counters. This section describes the format of the information returned by an EGetInfo call when the current network connection is through an Ethernet NB Card, an Ethernet LC Card, or through the built-in Ethernet available on the Macintosh Quadra 700/900/950.
EGetInfo Changes
The EGetInfo call can return up to 60 additional bytes of new information making the maximum number of bytes returned 78. As with the Apple EtherTalk NB Card (Apple/3Com card), the first 6 bytes returned contain the card’s Ethernet address. The remaining bytes that are returned contain information different from that returned with the Apple EtherTalk NB Card.
The next 12 bytes (offset 6–17) returned contain NO information but are always returned zero filled for compatibility. The remaining 60 bytes returned contain SONIC chip network statistic counters. The counters are listed below in the following table with the decimal and hexadecimal offsets given from the start of the return buffer. Note that the offset of the first item in the return buffer, the Ethernet address, is at offset 0.
Byte offset:(start at 0) Description
18 ($12) - Frames transmitted OK
22 ($16) - Single collision frames
26 ($1A) - Multiple collision frames
30 ($1E) - Collision frames
34 ($22) - Frames with deferred transmission
38 ($26) - Late collision
42 ($2A) - Excessive collisions
46 ($2E) - Excessive deferrals
50 ($32) - Internal MAC transmit error
54 ($36) - Frames received OK
58 ($3A) - Multicast frames received OK
62 ($3E) - Broadcast frames received OK
66 ($42) - Frame check sequence errors
70 ($46) - Alignment errors
74 ($4A) - Frames lost due to internal MAC
receive error
With the release of AppleTalk version 58, a minor change was implemented into the EGetInfo call such that the number of bytes filled in by the call, is returned in the eDataSize field. The re-vised parameter block description for the .ENET driver supplied with AppleTalk version 58 is:
Distinguishing Apple’s SONIC-Based Ethernet Systems
When making the EGetInfo call, it is important to pass the correct size buffer. The control call will only fill in the buffer with the number of bytes specified in the eBuffSize field. Unless it is already known that the active Ethernet card is the Apple (3Com) EtherTalk NB Card, it is recommended that you pass a buffer large enough to accommodate the additional information returned by the driver for the SONIC chip. One method to distinguish the Apple (3Com) EtherTalk NB Card from Apple’s SONIC-based systems, is to fill the 78-byte buffer with a byte pattern like 0xFF. For the Apple EtherTalk NB Card, the last 60 bytes of the buffer will still be filled with the byte pattern. For Apple’s SONIC-based systems, the last 60 bytes of the buffer will not all contain the byte pattern.
With the Ethernet driver released under AppleTalk version 58, an alternate method to distinguishing the two Apple Ethernet hardware cards is to pass in a pointer to a 78-byte buffer in the ePointer field, then to check the EDataSize value for the number of bytes filled into the buffer. For the original EtherTalk NB card, the number of returned bytes is 18; for the Ethernet NB card, the number of returned bytes will be 78.
Correction to the ENET.h Header File
Programs written for compilation with MPW C, which use the ENET.h header file supplied with MPW version 3.2.x are alerted to the fact the following declaration is incorrect. Users of Think C should check their ENET.h header file for the same error, as the version 5.0.x product was shipped with the header files supplied by the MPW team. This problem does not affect the corresponding Pascal interface file.
typedef struct {
EParamHeader
EParamMisc1 EParms1;
char eMultiAddr[5]; /*Multicast Address*/
}EParamMisc2;
The correct declaration has the eMultiAddr field immediately following the EParamHeader structure and the character array allocated 6 instead of 5 bytes as follows:
typedef struct {
EParamHeader
char eMultiAddr[6]; /*Multicast Address*/
}EParamMisc2;
The EParamMisc2 structure applies only to the EAddMulti and EDelMulti control calls to the Ethernet, token ring and FDDI drivers. If you are using these calls, you might include a revised structure declaration in your source code file so that you need not worry about overwriting the corrected header file when supplied with a new version of MPW. The declaration would be as follows:
#include <ENET.h>
.
.
/* The following structure declaration replaces the incorrect EParamMisc2
* structure declaration presented in the ENET.h files supplied with MPW
* to v3.2.4 and possibly greater.
*/
typedef struct {
EParamHeader
char eMultiAddr[6]; /*Multicast Address*/
}EParamMultiCast;
AppleTalk Multiple Node Architecture
Supporting multiple node addresses on a single machine connected to AppleTalk is a feature that has been created to support software applications such as AppleTalk Remote Access. Its implementation is general enough to be used by other applications as well.
Note: AppleTalk version 57 or later is required to support the AppleTalk Multiple Node Architecture. Version 57 is compatible with system software version 6.0.5 and later. If you implement multinode functionality into your program you should also plan to include AppleTalk version 57 with your product. Contact Apple’s Software Licensing department (see end of this Note) for information on licensing AppleTalk.
What Is It?
Multiple Node AppleTalk provides network node addresses that are in addition to the normal (user node) DDP address assigned when AppleTalk is opened. These additional addresses have different characteristics from those of the user node address. They are not connected to the protocol stack above the data link layer. When an application acquires a multinode, the application has to supply a receive routine through which AppleTalk will deliver broadcasts and packets directed to that multinode address.
The number of multinode addresses that can be supported on one single machine is determined by a static limit imposed by the AppleTalk ADEV itself (for example, EtherTalk). The limit is currently 253 nodes for Apple’s implementation of EtherTalk ($0, $FF, and $FE being invalid node addresses) and 254 for LocalTalk ($0 and $FF being invalid node addresses). The number of receive routines that .MPP supports is determined by the static limit of 256. If all of the multiple nodes acquired need to have unique receive routines, then only a maximum of 256 nodes can be acquired, even if the ADEV provides support for more than 256 nodes. .MPP will support the lesser of either the maximum of 256 receive routines, or the node limit imposed by the ADEV.
Outbound DDP packets can be created with a user-specified source network, node, and socket (normally equal to a multinode address) with the new Network Write call. With this capability and the packet reception rules described above, a single machine can effectively become several nodes on a network. The user node continues to function as it always has.
Glue Code for Multinode Control Calls
The following files are provided for C and Pascal programmers to implement the new multinode calls presented in this Tech Note. First, for C programmers:
Things You Need to Know When Writing a Multinode Application
Two new .MPP driver control calls have been added to allow multinode applications to add and remove multinodes.
AddNode (csCode=262)
A user can request an extra node using a control call to the .MPP driver after it has opened. Only one node is acquired through each call.
Parameter Block:
--> 24 ioRefNum short ; driver ref. number
--> 26 csCode short ; always = AddNode (262)
--> 36 reqNodeAddr AddrBlock ; the preferred address requested
; by the user.
<-- 40 actNodeAddr AddrBlock ; actual node address acquired.
--> 44 recvRoutine long ; address of the receive routine ; for MPP to call during packet ; delivery.
--> 48 reqCableLo short ; the preferred range
--> 50 reqCableHi short ; node being acquired.
--> 52 reserved[70] char ; 70 reserved bytes
AddrBlock:
aNet short ; network #
aNode unsigned chae ; node #
aSocket unsigned char ; should be zero for this call.
The AddNode call must be made as an IMMEDIATE control call at system task time. The .MPP driver will try to acquire the requested node address. The result code will be returned in the ioResult field in the parameter block. The result code –1021 indicates that the .MPP driver was unable to continue with the AddNode call because of the current state of .MPP. The caller should retry the AddNode call (the retry can be issued immediately after the AddNode call failed with error–1021) until a node address is successfully attained or another error is returned.
If the requested node address is zero, invalid, or already taken by another machine on the network, a random node address will be generated by the .MPP driver. The parameters reqCableLo and reqCableHi will be used only if there is no router on the network and all the node addresses in the network number specified in NetHint (the last used network number stored in parameter RAM) are taken up.
In this case, the .MPP driver tries to acquire a node address from the network range as specified by reqCableLo and reqCableHi. The network range is defined by the seed router on a network. If a specific cable range is not important to the application, set the reqCableLo and reqCableHi fields to zero. The recvRoutine is an address of a routine in the application to receive broadcasts and directed packets for the corresponding multinode.
Possible Error Codes:
noErr 0 ; success
tryAddNodeAgainErr -1021 ; MPP was not able to add node, ; try again.
MNNotSupported -1022 ; Multinode is not supported by
; the current ADEV.
noMoreMultiNodes -1023 ; no node address is available on ; the network.
RemoveNode (csCode=263)
This call removes a multinode address and must be made at system task time. Removal of the user node is not allowed.
Parameter Block:
--> 24 ioRefNum word ; driver ref. number
--> 26 csCode word ; always = RemoveNode (263)
--> 36 NodeAddr AddrBlock ; node address to be deleted.
Possible Error Codes:
noErr 0 ; success
paramErr -50 ; bad parameter passed
Receiving Packets
Broadcast packets are delivered to both the user’s node and the multinodes on every machine. If several multinodes are acquired with the same recvRoutine address, the recvRoutine, listening for these multinodes, will be called only once in the case of a broadcast packet.
Multinode receive handlers should determine the number of bytes already read into the Read Header Area (RHA) by subtracting the beginning address of the RHA from the value in A3 (see Inside Macintosh Volume II, page 326, for a description of the Read Header Area). A3 points past the last byte read in the RHA. The offset of RHA from the top of the .MPP variables is defined by the equate ToRHA in the MPW include file ATalkEqu.a. The receive handler is expected to call ReadRest to read in the rest of the packet. In the case of LocalTalk, ReadRest should be done as soon as possible to avoid loss of the packet. Register A4 contains the pointer to the ReadPacket and ReadRest routines in the ADEV.
To read in the rest of the packet,
JSR 2(A4)
On entry:
A3 pointer to a buffer to hold the bytes
D3 size of the buffer (word), which can be zero to throw away packet
On exit:
D0 modified
D1 modified
D2 preserved
D3 Equals zero if requested number of bytes was read; is less than zero if packet was –D3 bytes too large to fit in buffer and was truncated; is greater than zero if D3 bytes were not read (packet is smaller
than buffer)
A0 preserved
A1 preserved
A2 preserved
A3 pointer to 1 byte after the last byte read
For more information about ReadPacket and ReadRest, refer to Inside Macintosh Volume II, page 327.
A user can determine if a link is extended by using the GetAppleTalkInfo control call. The Configuration field returned by this call is a 32-bit word that describes the AppleTalk configuration. Bit number 15 (0 is LSB) is on if the link in use is extended. Refer to Inside Macintosh Volume VI, page 32-15.
Sending Datagrams Through Multinodes
To send packets through multinodes, use the new .MPP control call, NetWrite. NetWrite allows the owner of the multinode to specify a source network, node, and socket from which to send a datagram.
NetWrite (csCode=261)
Parameter Block:
--> 26 csCode word ; always NetWrite (261)
--> 29 checkSumFlag byte ; checksum flag
--> 30 wdsPointer pointer ; write data structure
Possible Error Codes:
noErr 0 ; success
ddpLenErr -92 ; datagram length too big
noBridgeErr -93 ; no router found
excessCollsns -95 ; excessive collisions on write
This call is very similar to the WriteDDP call. The key differences are as follows:
• The source socket is not specified in the parameter block. Instead it is specified along with the source network number and source node address in the DDP header pointed to by the write-data structure (WDS). Furthermore, the socket need not be opened. Refer to Inside Macintosh Volume II, page 310, for a description of the write-data structure. It is important to note that the caller needs to fill in the WDS with the source network, source node, and source socket values. .MPP does not set these values for the NetWrite call.
• The checkSumFlag field has a slightly different meaning. If true (nonzero), then the checksum for the datagram will be calculated prior to transmission and placed into the DDP header of the packet. If false (zero), then the checksum field is left alone in the DDP header portion of the packet. Thus if a checksum is already present, it is passed along unmodified. For example, the AppleTalk Remote Access program sets this field to zero, since remote packets that it passes to the .MPP driver already have valid checksum fields. Finally, if the application desires no checksum, the checksum field in the DDP header in the WDS header must be set to zero.
Datagrams sent with this call are always sent using a long DDP header. Refer to Inside AppleTalk, second edition, page 4-16, for a description of the DDP header. Even if the destination node is on the same LocalTalk network, a long DDP datagram is used so that the source information can be specified. The LAP header source node field will always be equal to the user node address (sysLapAddr), regardless of the source node address in the DDP header.
AppleTalk Remote Access Network Number Remapping
Network applications should be careful not to pass network numbers as data in a network transaction. AppleTalk Remote Access performs limited network number remapping. If network numbers are passed as data, they will not get remapped. AppleTalk Remote Access recognizes network numbers in the DDP header and among the various standard protocol packets, NBP, ZIP, RTMP, and so on.
Is There a Router on the Network?
Do not assume that there are no routers on the network if your network number is zero. With AppleTalk Remote Access, you can be on network zero and be connected to a remote network. Network applications should use the GetZoneList or the GetBridgeAddress calls to determine if there is a router on the network.
New for AppleTalk ADEVs
First, a word from our sponsors: The information in this section is provided to assist ADEV developers in updating their products for compatibility with AppleTalk Remote Access. If you are a Ethernet or token ring developer, MacDTS strongly urges that you consider following the Multivendor ADEV Architecture described earlier. For developers of Fiber Data Distribution Interface (FDDI) network interface cards, please contact Apple Software Licensing for information on licensing the new FDDI Phase 2 ADEV and Driver shell.
Several new calls have been implemented into the .MPP driver for AppleTalk version 57. Two calls, AOpen and AClose, were built into AppleTalk version 54 and later, and are also documented here. These calls notified the ADEV of changes in the status of the .MPP driver. For AppleTalk version 57, three new calls, AAddNode, ADelNode, and AGetNodeRef, plus a change to the AGetInfo call, were implemented to support the Multiple Node Architecture.
With the release of AppleTalk version 58, support is provided for the Simple Network Management Protocol (SNMP), and for the new Router Manager product. Programmer’s Guides for each of these products are available from APDA. For all ADEVs, an important change is required for the Router Manager product to provide basic SNMP support. An ADEV must be modified to support a minor change in the AGetInfo call. The ADEV must respond to the AGetInfo call by returning the slot number of the network device being supported, in the second reserved byte. This change is required so that when queried by a console, the Router Manager can report the slot number of the connection being supported. For those network devices running via the LocalTalk ports, the second reserved byte should continue to return zero. There is no support for such ADEVs at this time.
EtherTalk Phase 2, version 2.3, and TokenTalk phase 2, version 2.4, drivers support the new Multiple Node Architecture. Both drivers and AppleTalk version 57 are available through the Network Software Installer, version 1.1. As mentioned previously, AppleTalk version 57 and these drivers are compatible with system software version 6.0.5 and later. Note that the AppleTalk Remote Access product includes the EtherTalk Phase 2, version 2.3 driver, but not the multinode-compatible TokenTalk Phase 2, version 2.4, driver. Token ring developers, who license TokenTalk Phase 2, version 2.2 and earlier, should contact Apple’s Software Licensing department.
The following information describes changes to the ADEV that are required for multinode compatibility. This information is of specific importance to developers of custom ADEVs. The ADEV can be expected to function under version 6.0.5 and later. A version 3 ADEV must be used with AppleTalk version 57 or later. Developers of custom ADEVs will want to contact Software Licensing to license AppleTalk version 57.
For compatibility with Multinode AppleTalk, the 'atlk' resource of an ADEV must be modified to respond to these calls as described below. To determine whether an ADEV is multinode compatible, the .MPP driver makes an AGetInfo call to determine whether the ADEV version is 3 or later. Any ADEVs responding with a version of 3 or later must be prepared to respond to the new calls: AAddNode, ADelNode, and AGetNodeRef. See the Macintosh AppleTalk Connections Programmer’s Guide for more information about writing an AppleTalk ADEV.
The desired architecture for a multinode-compatible ADEV is such that it delivers incoming packets to the LAP Manager along with an address reference number, AddrRefNum. The LAP Manager uses the AddrRefNum to locate the correct receive routine to process the packet. For broadcast packets, the LAP Manager handles multiple deliveries of the packet to each multinode receive routine.
The .MPP driver for AppleTalk version 57 supports the new control call to add and remove multinodes, along with the network write call that allows the specification of the source address. .MPP includes a modification in its write function to check for one multinode sending to another. .MPP supports intermultinode transmission within the same machine. For example, the user node may want to send a packet to a multinode within the same system.
AGetInfo (D0=3)
The AGetInfo call should be modified to return the maximum number of AppleTalk nodes that can be provided by the atlk. This limit will be used by .MPP to control the number of multinodes that can be added on a single machine. The new interface is as follows:
Call: D1 (word) length (in bytes) of reply buffer
A1 -> Pointer to GetInfo record buffer
Return: A1 -> Pointer to GetInfo record
D0 nonzero if error (buffer is too small)
AGetInfoRec = RECORD
<-- version: INTEGER; { version of ADEV, set to three (3) }
<-- length: INTEGER; { length of this record in bytes }
<-- speed: LongInt; { speed of link in bits/sec }
<-- BandWidth: Byte; { link speed weight factor }
<-- reserved: Byte; { set to zero }
<-- slot: Byte; { device slot number or zero for
( LocalTalk ports }
<-- reserved: Byte; { set to zero }
<-- flags: Byte; { see below }
<-- linkAddrSize: Byte; { of link addr in bytes }
<-- linkAddress: ARRAY[0..5] OF Byte;
<-- maxnodes: INTEGER;
END;
flags: bit 7 = 1 if this is an extended AppleTalk, else 0
bit 6 = 1 if the link is used for a router-only connection (reserved
for half-routing)
bit 5 through 0 reserved, = 0
maxnodes is the total number of nodes (user node and multinodes) the ADEV supports. If a version 3 ADEV does not support multinodes, it must return 0 or 1 in the maxnodes field in AGetInfoRec and the ADEV will not be called to acquire multinodes. The version 3 ADEV will be called by .MPP in one of the following two ways to acquire the user node:
• If the ADEV returns a value of 0 in maxnodes, .MPP will issue Lap Write calls to the ADEV with D0 set to $FF indicating that ENQs should be sent to acquire the user node. .MPP is responsible for retries of ENQs to make sure no other nodes on the network already have this address. This was the method .MPP used to acquire the user node before multinodes were introduced. This method of sending ENQs must be available, even though the new AAddNode call is provided, to allow older versions of AppleTalk to function properly with a version 3 ADEV.
• If the ADEV returns a value of 1 in maxnodes, the new AAddNode function will be called by .MPP to acquire the user node.
For values of maxnode greater than 1, the new AAddNode function will be called by .MPP to acquire the additional multinodes.
AAddNode (D0=9)
This is a new call that is used to request the acquisition of an AppleTalk node address. It is called by the .MPP driver during the execution of the AddNode control call mentioned earlier. The ADEV is responsible for retrying enough ENQs to make sure no other nodes on the network already have the address. .MPP makes this call only during system task time.
Call: A0-> Pointer to parameter block
Return: D0 = zero if address was acquired successfully
--> NumTrys DS.W 1 ; offset 0x20 # of tries for address
--> DRVRPtr DS.L 1 ; offset 0x22 ptr to .MPP vars
--> PortUsePtr DS.L 1 ; offset 0x26 ptr to port use byte
--> AddrRefNum DS.W 1 ; offset 0x2A address ref number used ; by .MPP
EndR
The offset values describe the location of the fields from the beginning of the parameter block pointed to by A0. atlkPBRec is the standard parameter block record header for a _Control call. The field NetAddr is the 24-bit AppleTalk node address that should be acquired. The node number is in the least significant byte 0 of NetAddr. The network number is in bytes 1 and 2 of NetAddr; byte 3 is unused. NumTrys is the number of tries the atlk should send AARP probes on non-LocalTalk networks to verify that the address is not in use by another entity. On LocalTalk networks, NumTrys x 32 number of ENQs will be sent to verify an address.
DRVRPtr and PortUsePtr are normally passed when the atlk is called to perform a write function. For ADEVs that support multinodes, AppleTalk calls the new AAddNode function rather than the write function in the ADEV to send ENQs to acquire nodes. However, the values DRVRPtr and PortUsePtr are still required for the ADEV to function properly and are passed to the AAddNode call. AddrRefNum is a reference number passed in by .MPP. The ADEV must store each reference number with its corresponding multinode address. The use of the reference number is described in the following two sections.
For multinode-compatible ADEVs, .MPP issues the first AAddNode call to acquire the user node. The AddrRefNum associated with the user node must be 0xFFFF. It is important to assign 0xFFFF as the AddrRefNum of the user node, and to disregard the AddrRefNum passed by .MPP for the user node. See the discussion at the end of the ADelNode description.
ADelNode (D0=10)
This is a new call that is used to remove an AppleTalk node address. It can be called by the .MPP driver to process the RemoveNode control call mentioned earlier.
Call: A0-> Pointer to parameter block
NetAddr contains the node address to be deleted
Return: D0 = zero if address is removed successfully
≠ zero if address does not exist
atlkPBRec.AddrRefNum = AddrRefNum to be used by .MPP if the operation is successful
<-- AddrRefNum DS.W 1 ; offset 0x2A AddrRefNum ; passed in by AAddNode
; on return
EndR
The field NetAddr is the 24-bit AppleTalk node address that should be removed. As with the AAddNode selector, the node number is in the least significant byte 0 of NetAddr. The network number is in bytes 1 and 2 of NetAddr; byte 3 is unused. The address reference number, AddrRefNum, associated with the NetAddr, must be returned to .MPP in order for .MPP to clean up its data structures for the removed node address.
As mentioned above, a value of 0xFFFF must be returned to .MPP after deleting the user node. When the AppleTalk connection is started up for the first time on an extended network, the ADEV can expect to process an AAddNode request followed shortly by an ADelNode request. This results from the implementation of the provisional node address for the purpose of talking with the router to determine the valid network number range to which the node is connected. After obtaining the network range, .MPP issues the ADelNode call to delete the provisional node. The next ADelNode call will be to acquire the unique node ID for the user node. As mentioned previously, .MPP can pass a value different from 0xFFFF for the user node. The user node is acquired before any multinode. The ADEV needs to keep track of the number of AAddNode and ADelNode calls issued to determine whether the user node is being acquired. Refer to Inside AppleTalk, second edition, page 4-8, for additional information.
AGetNodeRef (D0=11)
This is a new call that is used by .MPP to find out if a multinode address exists on the current ADEV. This call is currently used by .MPP to check if a write should be looped back to one of the other nodes on the machine (the packet does not actually need to be sent through the network) or should be sent to the ADEV for transmission.
Call: A0-> Pointer to parameter block
Return: D0-> = zero if address does not exist on this machine
≠ zero if address exists on this machine
atlkPBRec.AddrRefNum = AddrRefNum (corresponding to the node address) if the operation is successful
<-- AddrRefNum DS.W 1 ; offset 0x2A AddrRefNum ; passed in by AAddNode
; on return
EndR
The field NetAddr is the 24-bit AppleTalk node address whose AddrRefNum is requested. The node number is in the least significant byte 0 of NetAddr. The network number is in bytes 1 and 2 of NetAddr; byte 3 is unused. The address reference number, AddrRefNum, associated with the NetAddr, must be returned to .MPP. Remember to return 0xFFFF as the AddrRefNum for the user node.
AOpen (D0=7)
Call:
--> D4.B current port number
ADEVs should expect the AOpen call whenever the .MPP driver is being opened. This is a good time for the ADEV to register multicast addresses with the link layer or register a Transition Queue handler. After this call is completed, .MPP is ready to receive packets. If the ADEV does not process this message, simply return, RTN with a ControlErr.
Note that AOpen is not specific to the Multinode Architecture.
AClose (D0=8)
AClose is called only when .MPP is being closed (for example, .MPP is closed when the “inactive” option is selected in the Chooser or when the user switches links in network cdev). The ADEV can use this event to deregister any multicast addresses with the link layer or remove an existing Transition Queue handler. After this AClose call is completed, the ADEV should not defend for any node addresses until .MPP reopens and acquires new node addresses. If the ADEV does not process this message, simply return, RTN with a ControlErr.
Note that AClose is not specific to the Multinode Architecture.
For comparison, descriptions of AInstall and AShutDown are documented as follows:
AInstall (D0=1)
Call:
--> D1.L = value from PRAM (slot, ID, unused, atlk resource ID)
<-- D1.L = high 3 bytes for parameter RAM returned by the ADEV, if no error
<-- D0.W = error code
The AInstall call is made before .MPP is opened either during boot time or when the user switches links in network cdev. This call is made during system task time so that the ADEV is allowed to allocate memory, make file system calls, or load resources and so on. Note: AOpen call will be made during .MPP opens.
AShutDown (D0=2)
ADEVs should expect the AShutDown call to be made when the user switches links in the Network cdev. The network cdev closes .MPP, which causes the AClose call to be made before the cdev issues the AShutDown call. Note: the AShutDown call is always made during system task time; therefore, deleting memory, unloading resources, and file system calls can be done at this time.
Receiving Packets
The address reference number (AddrRefNum) associated with each node address must be passed to .MPP when delivering packets upward. When making the LAP Manager call LReadDispatch to deliver packets to AppleTalk, the ADEV must fill the high word of D2 in with the address reference number, corresponding to the packet’s destination address (LAP node address in the LocalTalk case and DDP address in the non-LocalTalk case). There are a few special cases:
• In the case of broadcasts and packets directed to the user node, $FFFF (word) should be used as the address reference number.
• On non-LocalTalk networks, packets with DDP destination addresses matching neither the user node address nor any of the multinode addresses should still be delivered to the LAP Manager so that the router can forward the packet on to the appropriate network. In this case, the high word of D2 should be filled in with the address reference number, $FFFE, to indicate to MPP that this packet is not for any of the nodes on the machine in the case of a router running on a machine on an extended network.
• On LocalTalk networks, the ADEV looks only at the LAP address; therefore, if the LAP address is not the user node, one of the multinodes, or a broadcast, the packet should be thrown away.
Defending Multinode Addresses
Both LocalTalk (RTS and CTS) and non-LocalTalk (AARP) ADEVs have to be modified to defend not only for the user node address but also for any active multinode addresses.
Corrections/Clarifications to the LAP Manager
The interface for the Link Access Protocol (LAP) Manager is presented in the document Macintosh AppleTalk Connections Programmer’s Guide, available from APDA, p/n M7056/A. This section provides additional descriptions to the LAP Manager functions described in the Programmer’s Guide.
LRdDispatch (D0 = 1)
The LRdDispatch routine is called by an ADEV’s 'atlk' packet handling routine to notify the LAP Manager that a packet has been received, and to pass the packet to the LAP Manager for processing by the appropriate protocol handler. The documentation indicates that this routine “even though it is called with a JSR, does not return to the caller, but jumps to the protocol handler that is attached to the protocol indicated in (register) D2.”
When called to handle LRdDispatch, the LAP Manager searches its protocol table for a match to the protocol specified in D2. If found, the return address placed on the stack by the JSR instruction is removed. For this reason, the caller will not be returned to if a protocol handler is found. This also means that the packet handling routine that calls LRdDispatch must restore the stack to the state the stack was in when the packet handler was entered.
LWrtInsert (D0 = 2)
The LWrtInsert description indicates that setting bit 6 of the flag byte in register D1, “does not disable the port B serial communications controller (SCC).…” This bit no longer has any meaning under AppleTalk.
AppleTalk Version Information
The following table is presented to assist AppleTalk developers in understanding which versions of AppleTalk are required by the various AppleTalk products. This list does not identify the individual bug fixes associated with each release of AppleTalk.
AppleTalk Version .MPP Version .ATP Version
Apple Products Using That Version
19 19 19 Macintosh Plus ROM
48 48 46 Macintosh SE ROM
Macintosh Classic ROM
48.1 48 46 AppleShare File Server v1.0
49 49 49 Macintosh II ROM
Macintosh IIcx ROM
Macintosh SE/30
50 50 49 AppleShare File Server v1.1
51 51 51 AppleShare Print Server v2.0
52 52 52 AppleShare File Server v2.0
Macintosh IIx ROM
Macintosh IIci ROM
Macintosh Portable ROM
PowerBook 100 ROM
Phase 1 drivers
AppleTalk Version .MPP Version .ATP Version
Apple Products Using That Version
53 53 53 AppleTalk Phase 2 products
AppleTalk Internet Router v2.0
Apple EtherTalk NB Card 2.0
Apple TokenTalk NB Card 2.0
54 54 54 Macintosh IIfx
Macintosh LC, LC II, & IIsi
55 55 55 Apple Ethernet LC Card (for Macintosh LC)
56 56 56 System 7.0, 7.0.1
Macintosh Classic II
PowerBook 140, 160, 170, 180
Macintosh Quadra 700, 900, 950
57.0.1 57.0.1 57.0.1 AppleTalk Remote Access
Apple TokenRing 4/16 NB Card
Apple Ethernet NB Card
57.0.3 57.0.3 57.0.3 Apple Ethernet LC Card (for Macintosh LC II)
57.0.4 57.0.4 57.0.4 MacTCP Token Ring Extension v1.0
System 7.1, MacTCP 1.1.1
Macintosh Duo 210, 230
Macintosh IIvi, IIvx
Macintosh Color Classic
Macintosh LC II
PowerBook 165c
Macintosh Quadra 800
Macintosh Centris 610, 650
58 58 58 Apple Internet Router v3.0
Mac SNMP
Phase 2 drivers
Some interesting notes:
• .MPP and .ATP driver versions weren’t always the same in versions of AppleTalk before version 51. The .MPP driver version is the AppleTalk version number.
• The Phase 1 RAM-based drivers (versions 49 through 52) were supplied as file that could be drag-installed (that is, the installation consisted of dropping them into the System Folder).
• The Phase 2 RAM-based drivers (versions 53 through 58) must be installed by an Installer script that will install the various system pieces (files, resources, and so on) needed to load and support these new drivers; these versions cannot be drag-installed.
• AppleTalk version 56 or greater includes the .DSP driver (ADSP). Starting with version 56, the .DSP driver version is the same as the AppleTalk version.
Apple software products that require the Phase 2 RAM-based drivers must be installed using the Installer program. Apple supplies an Installer script that will copy all files and system resources needed. Apple licenses the source to an Installer script that you can use if you license AppleTalk to ship with your products.
Contacting Apple Software Licensing
Software Licensing can be reached as follows:
Software Licensing
Apple Computer, Inc.
20525 Mariani Avenue, M/S 38-I
Cupertino, CA 95014
MCI: 312-5360
AppleLink: SW.LICENSE
Internet: SW.LICENSE@AppleLink.Apple.com
(408)974-4667
Further Reference:
• Inside AppleTalk, Second Edition, Addison-Wesley
• Inside Macintosh, Volume II, The AppleTalk Manager, Addison-Wesley
• Inside Macintosh, Volume V, The AppleTalk Manager, Addison-Wesley
• Inside Macintosh, Volume VI, The AppleTalk Manager, Addison-Wesley
• Macintosh AppleTalk Connections Programmer’s Guide, Final Draft 2, Apple Computer, Inc. (M7056/A)
• AppleTalk Phase 2 Protocol Specification, Apple Computer, Inc. (C0144LL/A)
• AppleTalk Remote Access Developer’s Toolkit, Apple Computer, Inc. (R0128LL/A)
• M.NW.AppleTalk2Mac
NuBus is a trademark of Texas Instruments.
NW 14 - AppleTalk Timers Explained
Networking
Written by: Sriram Subramanian & Pete Helme April 1990
This Technical Note explains how to effectively use timers and retry mechanisms of the various AppleTalk protocols to achieve maximum performance on an internet.
The most fundamental service in an AppleTalk internet is the Datagram Delivery Protocol (DDP), which provides a best-effort, connectionless, packet delivery system. A sequence of packets sent using DDP on an AppleTalk internet between a pair of machines may traverse a single high-speed Ethernet network or it may wind across multiple intermediate data links such as LocalTalk, TokenRing, etc., which are connected by routers. Some packet loss is always inevitable because of the loosely coupled nature of the underlying networks. Even on a single high-speed Ethernet network, packets can be lost due to collisions or a busy destination node. The AppleTalk Transaction Protocol (ATP), the AppleTalk Data Stream Protocol (ADSP), and other high-level protocols protect against packet loss and ensure reliability by using positive acknowledgement with packet retransmission mechanism.
The basic transaction process in ATP consists of a client in a requesting node sending a Transaction Request (TReq) packet to a client in a responding node. The client in the responding node is expected to service the request and generate a series of Transaction Response (TResp) packets, which also serves as an acknowledgement. The ATP process in the requesting node also starts a timer when it sends a packet and retransmits a packet if the timer expires before a complete response arrives. In a large internet with multiple gateways, it is impossible to know how quickly acknowledgements may return to the requestor. If you set the retry time to be too small, you may be retransmitting a request while a delayed response is en route, but if you wait too long to retransmit a request, application performance may suffer. More importantly, the delay at each gateway depends upon the traffic, so the time required to transmit a packet and receive an acknowledgement varies from one instant to another. To further complicate matters, two packets sent back to back could take completely different routes to the destination.
Selecting ATP Retry Time And Retry Count
You can use the round trip time for a transaction as a heuristic for setting the retry time and retry count. The round trip time between two nodes in a particular internet at a particular time is usually deterministic.
The easiest way to set the retry time is to assign a static value based on the round trip time for a transaction. The AppleTalk Echo Protocol (AEP) can be used to obtain the round trip time in a given moment between two nodes. AEP is implemented in each node as a DDP client residing on statically-assigned socket number four. You should use DDP to send AEP requests through any socket that is available, and you should use the maximum packet size that you plan on using in your application. You can listen for AEP responses by implementing a socket listener. The following code is an example AEP socket listener.
CMP.B #longDDP, D2 ; check for long header (Type #2 packet)
BNE.S noHops ; wah... no hops if short packet
MOVE.B lapType+1(A3), D2 ; this is the hop count byte, 1st byte in DDP
; header
AND.B #$3C, D2 ; mask to middle 4 bits of byte for hop count
; | x | x | H | O | P | S | x | x |
ASR.B #2, D2 ; shift 2 bits to right
LEA our_Hops, A3 ; address of our storage
MOVE.B D2, (A3) ; move # of hops into our storage
noHops
MOVE.W #DDPMaxData, D3 ; our buffer is #DDPMaxData in size
LEA our_Buff, A3 ; address of buffer to read packet into
MOVE.L (A3), A3 ; set buffer
JSR 2(A4) ; ReadRest of packet into buffer
BEQ.S RcvEchoReply ; If no error, continue
BRA.S RcvEchoFail ; dang…
RcvEIgnore
CLR D3 ; Set to ignore packet
JMP 2(A4) ; Ignore it, ReadRest and return
BRA.S RcvEchoFail
RcvEchoReply
CMP.B #EPReply, -DDPMaxData(A3) ; make sure it's our reply packet
; it shouldn't be anything else, but check
; just in case
BNE.S RcvEchoFail ; if not our reply then blow
MOVE.L A5, D2 ; save dude in D2
LEA our_A5, A5 ; address of our A5 local storage
MOVE.L (A5), A5 ; make A5 our A5 for application global use
MOVE.B #1, GBOB(A5) ; set flag confirming reception of
; echo reply packet
LEA our_Buff, A3 ; address of our local buffer storage into A3
MOVE.L (A3), A3 ; get saved pointer and set buffer.
LEA our_Hops, A5 ; address of hops local storage… notice we
; are TRASHING A5 with this!!!!!
MOVE.W (A5), (A3)+ ; copy in hop count to buffer
MOVE.L Ticks, (A3) ; next copy in Ticks
MOVE.L D2, A5 ; restore dude
RTS ; return to caller
RcvEchoFail
RTS ; return to caller
ENDP
setUpSktListener PROC EXPORT
IMPORT our_A5 : CODE
IMPORT our_Buff : CODE
LEA our_A5, A0 ; this copies
MOVE.L CurrentA5, (A0) ; this copies CurrentA5 into our local
; storage for global use in the listener
MOVE.W #DDPMaxData, D0 ; max size of data in a packet
_NewPtr CLEAR
BNE.S setUpFailed ; if NIL then forget it
LEA our_Buff, A1 ; we need to save the pointer reference
MOVE.L A0, (A1) ; in a place the listener can find it
MOVE.L A0, D0 ; return value to caller
RTS
setUpFailed
CLR.L D0 ; tell caller we failed by returning nil
; (caller expecting valid ptr returned)
RTS
ENDP
END
We now resume our regular programming…
You should typically get an AEP response packet within a few milliseconds. If there is no response for a period of time, typically about 10 seconds, you should resend your AEP request to account for a lost request or lost packets. To be really safe, you should resend your AEP request with different data to take into account the response to the first packet coming back later. The retry time could then be simply set to k*Round_Trip_Time, where the value of k depends upon the request semantics, like total data size.
This technique of statically setting the retry time is not always adequate to accommodate the varying delays encountered in a internet environment at different times. You could dynamically adjust the retry time based on an adaptive retransmission algorithm that continuously monitors round trip times and adjusts its timeout parameter accordingly. To implement an adaptive algorithm, you can record the round trip time for each transaction. One common technique is to keep the average round trip time as a weighted average and use new round trip times from transactions to change the average slowly. For example, one averaging technique* uses a constant weighing factor, q, where 0 ≤ q < 1, to weigh the oldest average against the latest round trip time:
Choosing a value for q close to 1 makes the weighted average immune to changes that last a short time. Choosing a value for q close to 0 makes the weighted average respond to changes in the delay very quickly.
The total time (i.e., retry time * retry count) before a request is concluded as failed could be anywhere from 10 seconds to a couple of minutes, depending on the type of the client application and the relative distance between the source and the destination.
*Douglass Corner, InterNetworking with TCP/IP. KARN, P. and C. PARTRIDGE [August 1987], “Improving Round-Trip Time Estimates in Reliable Transport Protocols”, Proceedings of ACM SIGCOMM 1987.
NBP Retry Counts
You cannot really use the AEP to estimate round trip times for NBP packets because you need to use NBP to determine the internet address of the node from which an echo is being sought. In this case, you have to use the type of device that you are looking for as a heuristic for setting the retry count. The LaserWriter, for example, may be busy and not respond to a LkUp packet. In such a case, you might want to do a quick lookup to return a partial list to the user like the Chooser. You could then do a longer lookup to get a more complete list of mappings. You should use a “back off” algorithm to make the subsequent lookups further apart to generate progressively less traffic. Name lookups are expensive and produce a lot of network traffic, and name confirmation is the recommended call to use when confirming mappings obtained through early bindings. Because Name lookups are expensive, you should avoid searching all the zones in the internet.
Setting TRel Timer in SendRequest
AppleTalk Phase 2 drivers allow you to set the TRel timer in SendRequest or NSendRequest calls with ATP XO (exactly once) service so as not to be locked into the pre-AppleTalk Phase 2 time of 30 seconds. You should set this timer based on the round trip time. Generally, if the round trip time is less than one second, the default TRel time setting of 30 seconds is adequate. If the round trip time is more, you can increase the TRel time proportionately.
xppTimeout and xppRetry
The two ZIP calls, GetZoneList and GetLocalZones, made on the .XPP driver contain the ATP retry interval (in seconds) and count, in the xppTimeout and xppRetry parameters. Both these functions are ATP request-response transactions between a node and a router on the network to which the requesting node is attached. The round trip is relatively short for this transaction, and you should have very small values of xppTimeout and xppRetry, typically two and three, respectively.
Further Reference:
• Inside AppleTalk
• Inside Macintosh, Volumes II & V, The AppleTalk Manager
• M.NW.Internets
• M.NW.AppleTalk2Mac
NW 15 - Arbitrating the Use of afpMiscUserCommand and afpMiscUserWrite
Networking
Written by: Jim Luther September 1992
This Technical Note discusses a scheme for arbitrating the use of the afpMiscUserCommand and afpMiscUserWrite AppleTalk Filing Protocol (AFP) commands.
Inside Macintosh Volume V lists two AFP command codes that are reserved for developers. They are afpMiscUserCommand (call number 191) and afpMiscUserWrite (call number 254). Several developers have asked that Apple arbitrate the use of those two AFP calls. This Technical Note describes our recommended solution.
Because afpMiscUserCommand and afpMiscUserWrite are reserved for developers, the format of the AFP request and reply blocks are undefined except for the first byte of the request block which contains the AFP call number. If the request block is further defined to include a word-aligned long value, that long value can be used to identify a specific developer request. Since most developers have probably already been assigned a unique 4-byte file creator type, we suggest reusing that creator type for the long value. Figure 1 shows the request blocks for afpMiscUserCommand and afpMiscUserWrite with the creator type value. The value of aspMaxCmdSize in the figure is returned by the ASPGetParms function.
Figure 1 afpMiscUserCommand and afpMiscUserWrite Request Blocks With Creator Type Identifier
Further Reference:
• Inside Macintosh, Volume V, The AppleTalk Manager
• M.NW.BorrowedAFP
NW 16 - Borrowed AFP Sessions
Networking
Written by: Jim Luther September 1992
This Technical Note shows how to borrow the session reference number of an AFP volume mounted by the Macintosh File System. It also shows how to retrieve other information from the file system for a mounted AFP volume.
Introduction
The AppleShare Chooser extension allows Macintosh applications to perform almost all volume and file access operations on an AppleTalk Filing Protocol (AFP) file server by translating File Manager commands to their AFP equivalent commands. To access a file server, an application normally calls the File Manager. The File Manager calls the AppleShare external file system (part of the AppleShare Chooser extension) which translates the File Manager command into an AFP call. The AppleShare external file system then calls the .XPP driver. The .XPP driver delivers the AFP call to the server and returns the reply to the AppleShare external file system. The AppleShare external file system translates the reply data (if any) and returns it to the File Manager which returns it to the application. Figure 1 shows the normal flow of commands between a Macintosh application and an AFP file server.
Figure 1 Application Using the File Server Through the File Manager
However, there are a few instances for which no equivalent File Manager commands exist to perform operations supported by AFP. In those instances, an application must use the .XPP driver to access the file server with AFP commands.
Applications accessing a file server with AFP commands need to have an open AFP session with the file server. When no session exists, the application must use the .XPP driver to open an AFP session with the afpLogin (and possibly afpLoginCont) command. However, when an AFP volume on the file server is already mounted by the Macintosh File System, a session is already open with the file server. If the session reference number is retrieved from the .AFPTranslator driver (another part of the AppleShare Chooser extension), that session can be used, with restrictions, to access the file server with AFP commands. Figure 2 shows the flow of commands when a Macintosh application accesses an AFP file server directly through the .XPP driver using the session reference number borrowed from the .AFPTranslator driver.
Figure 2 Application Using File Server Through the .XPP Driver
with Borrowed Session Reference Number
The next section of this Technical Note tells how to get the AFP session reference number for a mounted AFP volume from the .AFPTranslator driver. It also lists the restrictions you must observe when using the borrowed AFP session.
The Server Volume Information Status Call
The AppleShare external file system performs the translation of File Manager commands to AFP commands and maintains sessions with AFP file servers. The server volume information (AFPSVolInfo) status call to the .AFPTranslator driver can be used to retrieve several important pieces of information stored by the driver. The information returned by the AFPSVolInfo status call is:
• the AFP version used to open the session with the server. This lets you know what possible AFP calls can be made with this session.
• the session reference number. The session reference number is passed to the .XPP driver whenever you make an AFP call.
• the AFP volume ID number. This is the number you pass to AFP calls that require the volume ID number.
• the file server’s internet socket address. This is the same internet socket address returned by the File Manager PBHGetVolParms function in the vMServerAdr field of the GetVolParmsInfoBuffer record.
• the user authentication method (UAM) used to establish the session. This is the same word value returned by the File Manager PBHGetLogInInfo function in ioObjType and by the File Manager PBGetVolMountInfo function in the uamType field of the AFPVolMountInfo record.
• the user name used to establish the session. This is the same string returned by the File Manager PBHGetLogInInfo function in the string pointed to by ioObjNamePtr and by the File Manager PBGetVolMountInfo function as part of the AFPData field in the AFPVolMountInfo record (the exact location of the user name in the AFPData field in the AFPVolMountInfo record is determined by the userNameOffset field).
• the server’s volume icon and mask. This is the same 256-byte icon and mask returned by a control call to the disk driver with csCode = 21.
• the string displayed by the Finder’s Get Info dialog (after the word “Where:”). This is the same string returned by a control call to the disk driver with csCode = 21.
The information list above is returned in a GetVolSessInfoRec record. The GetVolSessInfoRec record is defined as follows:
sessUserNamePtr: StringPtr; {ptr to user name string}
sessVolIconPtr: Ptr; {ptr to server volume icon/mask}
sessWhereStringPtr: StringPtr; {ptr to "where" information string}
END;
Warning: sessUserNamePtr, sessVolIconPtr, and sessWhereStringPtr point to data owned by the .AFPTranslator driver. You must copy that data into your program variables before using it.
The fields in the ParamBlockRec record used for the AFPSVolInfo status call to the .AFPTranslator driver are defined as follows:
Æ 12 ioCompletion long pointer to completion routine
¨ 16 ioResult word result code
Æ 24 ioRefNum word .AFPTranslator reference number
Æ 26 csCode word always AFPSVolInfo
Æ 28 ioMisc long pointer to volume’s VCB
Æ 32 ioBuffer long pointer to GetVolSessInfoRec
Æ 36 ioReqCount long size of data requested
¨ 40 ioActCount long size of data returned
Here are the detailed descriptions of the parameter block fields:
ioCompletion Longword input pointer: If the AFPSVolInfo status cell is called asynchronously, this must be a pointer to the completion routine or NIL.
ioResult Word result value: The result code from the function.
ioRefNum Word input value: The driver reference number of the .AFPTranslator driver.
csCode Word input value: Always AFPSVolInfo (124).
ioMisc Longword input pointer: A pointer to the volume’s volume control block (VCB).
ioBuffer Longword input pointer: A pointer to the GetVolSessInfoRec where the server volume information is returned.
ioReqCount Longword input value: The size of the GetVolSessInfoRec pointed to by ioBuffer.
ioActCount Longword result value: The size of the data returned in the GetVolSessInfoRec pointed to by ioBuffer.
The following result codes can be returned by the AFPSVolInfo status call:
noErr 0 No error.
badUnitErr -21 The driver reference number is bad.
unitEmptyErr -22 The driver reference number is bad.
notOpenErr -28 The driver isn’t open.
statusErr -18 The driver can’t respond to this status call.
paramErr -50 Either ioReqCount indicates the GetVolSessInfoRec record is too small, or the volume specified by ioMisc is not owned by the .AFPTranslator driver.
The following code shows how to use the AFPSVolInfo status call to get the server volume information for the volume specified by its volume reference number.
USES
AppleTalk, Files;
CONST
{ AFP version numbers }
AFPVer1_1 = 1; { AFP version 1.1 }
AFPVer2_0 = 2; { AFP version 2.0 }
AFPVer2_1 = 3; { AFP version 2.1 }
AFPSVolInfo = 124; { server volume information call }
{ copy where information string into a string variable }
myWhereString := sessWhereStringPtr^;
{ at this point, you can use all of the information just copied }
{ from myGetVolSessInfoRec or still in myGetVolSessInfoRec }
DisposHandle(myIconHandle);
END;
END;
DoGetVolSessionInfo := err;
END;
Session Borrowing Rules and Restrictions
Warning: The restrictions listed in this Note must be observed when your program borrows an AFP session owned by the Macintosh File System.
There is a good reason why Apple has not documented the AFPSVolInfo status call in the past. AFP file servers differentiate users by their sessions and the AppleShare external file system makes certain assumptions about AFP volumes (and their contents) that it has open. If the session owned by the Macintosh File System is used improperly, you can confuse the AppleShare external file system or the file server. The basic rule you should use when borrowing an AFP session owned by the file system is
If it can be done with File Manager functions, use the File Manager functions—don’t use AFP calls.
That means you shouldn’t open or close volumes, directories, files, or a volume’s desktop database, you shouldn’t use calls that require a file or desktop database to be open, and you definitely should not close the AFP session. If you need to do any of those AFP operations, you should use the .XPP driver to open your own AFP session with the file server.
The following is a list of AFP calls that are safe to use with a session borrowed from the file system. For each AFP call, there’s an description of what you can do with the call that you cannot do with the File Manager functions.
afpGetSParms This call can be used to retrieve the server time and the list of server volumes. For each volume, you also can determine if the volume is password-protected and if the volume contains Apple II configuration information.
afpSetVolParms This call can be used to set the backup date of a volume.
afpChangePassword This call can be used to change the user’s password.
afpGetUserInfo This call can be used to retrieve the specified user’s user ID or primary group ID.
afpGetSrvrMsg This call can be used to retrieve the current greeting message or server message. This call is only supported by AFP 2.1 servers. Note: the server message may not be applicable to the user.
afpMiscUserCommand reserved for developer use. See Technical Note #323, “Arbitrating Use of afpMiscUserCommand and afpMiscUserWrite.”
afpMiscUserWrite reserved for developer use. See Technical Note #323, “Arbitrating Use of afpMiscUserCommand and afpMiscUserWrite.”
The list continues. However, these calls should be used only when you need to retrieve or set information (such as ProDOS information) that is inaccessible through File Manager functions.
afpEnumerate This call can be used to list the contents of a directory when either ProDOS information or specific file or directory attribute information is needed. For all other purposes, the File Manager’s PBGetCatInfo function should be used.
afpGetVolParms This call can be used to retrieve the parameters for a particular server volume. For most purposes, the File Manager’s PBHGetVInfo function should be used instead.
afpSetDirParms This call can be used to set parameters for a specified directory when either ProDOS information or specific directory attribute information must be set. For all other purposes, the File Manager’s PBSetCatInfo function should be used.
afpSetFileParms This call can be used to set parameters for a specified file when either ProDOS information or specific file attribute information must be set. For all other purposes, the File Manager’s PBSetCatInfo function should be used.
afpGetFlDrParms This call can be used to retrieve the parameters for a specified file or directory when either ProDOS information or specific file or directory attribute information is needed. For all other purposes, the File Manager’s PBGetCatInfo function should be used.
afpSetFlDrParms This call can be used to set parameters for a specified file or directory when either ProDOS information or specific file or directory attribute information must be set. For all other purposes, the File Manager’s PBSetCatInfo function should be used.
If the AppleShare 3.0 (or later) Chooser extension is used with System 6, you can make the following AFP 2.1 calls to an AFP 2.1 file server. These calls are not supported by the System 6 File Manager.
afpGetSrvrMsg See description in list above.
afpCreateID This call can be used to create a unique file ID for a specified file.
afpDeleteID This call can be used to invalidate all instances of the specified file ID.
afpResolveID This call can be used to return information (including the file location) of the specified file ID
afpExchangeFiles This call can be used to exchange the contents of two files on a server volume.
afpCatSearch This call can be used to search a volume for files or folders that match specified criteria.
Conclusion
The AFPSVolInfo status call to the .AFPTranslator driver returns useful information for developers who need to access an AFP file server in ways not supported by the Macintosh File System. However, the restrictions lists in this note must be observed to prevent problems on the client Macintosh or the AFP file server.
Further Reference:
• Inside Macintosh, Volume V, The AppleTalk Manager
• M.NW.afpMiscUserCommand
• Inside AppleTalk, Second Edition, AppleTalk Filing Protocol
• AppleShare 3.0 Developer’s Kit, AppleTalk Filing Protocol Version 2.1
NW 17 - Data Access Extensions
Networking
Written by: Chuq Von Rospach and Dan Strnad May 1992
This Technical Note discusses coding data access extensions that provide an interface between the Data Access Manager and remote data sources. Each of the functions that a data access extension must implement is described.
Introduction
A data access extension is a program that provides an interface between the Data Access Manager and the remote data source. The data access extension implements all of the low-level functions and handles network communication for the Data Access Manager. Because the data access extension implements the low-level Data Access Manager functions, it must return appropriate result codes and handle asynchronous execution of functions as appropriate.
Note: Each data access extension contains a flag that indicates to the Data Access Manager whether the data access extension supports asynchronous execution of routines. If an application attempts to make an asynchronous call to a data access extension that has the first bit (bit 0) of the flags field cleared to 0, the Data Access Manager returns a result code of rcDBAsyncNotSupp and terminates execution of the routine. To ensure compatibility of your data access extension with all applications, your data access extension should support asynchronous execution of functions. The data access extension flags field is described in the next section, “Contents of a Data Access Extension.”
As soon as the data access extension begins execution of an asynchronous routine, it should return a noErr result code for the function result and set the result field of the asynchronous parameter block to 1. It should return control to the calling routine as quickly as possible. When it terminates execution of the routine, the data access extension must place the return code in the result field. Result codes for each of the data access extension routines are listed in the next section. The asynchronous parameter block is described in “Asynchronous Execution of Routines” in the Data Access Manager chapter of Inside Macintosh Volume VI, page 8-50.
When the data access extension has completed execution of an asynchronous routine, it must call the application’s completion routine pointed to by the completionProc field of the asynchronous parameter block. The completion routine is described in “Asynchronous Execution of Routines” in the Data Access Manager chapter of Inside Macintosh Volume VI, page 8-50.
The data access extension can use the ddevRef field in the asynchronous parameter block for its own purposes.
This Tech Note describes each of the functions that a data access extension must implement.
Contents of a Data Access Extension
A data access extension consists of a file of type 'ddev', located in the Extensions Folder. The data access extension file must contain these resources:
'ddev' (function; resource ID is 128)
'STR ' (name of data access extension; resource ID is 128)
'dflg' (version number and flags; resource ID is 128)
The 'ddev' resource contains a function that implements all of the low-level Data Access Manager functions. The Data Access Manager calls the ddev function whenever the manager needs to execute a low-level function.
Here is a function declaration for a ddev function.
FUNCTION MyDDev(params: DDEVParams) : OSErr;
The params parameter is a parameter block that includes a routine selector. The data access extension parameter block is described in the next section, “Data Access Extension Parameters.”
You must set bit 6 of the resource attribute byte to 1 for the 'ddev' resource so that the resource is read into the system heap. Resource attributes are discussed in the Resource Manager chapter of of Inside Macintosh Volume I.
The 'STR ' resource must contain a character string of not more than 63 characters that specifies the name of the data access extension. Under tsystem 7.0 or later, the data access extension is assumed to reside in the "Extensions" folder within the System folder. The data access extension name is a parameter to the DBInit function.
The 'dflg' resource contains two 4-byte fields, as follows:
TYPE DDEVFlags =
RECORD
version: LongInt; {data access extension format}
flags: LongInt {data access extension flags}
END;
The version field indicates the version of the data access extension format used for this data access extension. It must be set to 0 for the version 7.0 Data Access Manager.
The flags field specifies flags that the data access extension must set. At present, only the least significant bit is defined; all other bits must be cleared to 0. Set the flags field to the constant kAsyncSupported (that is, set the least significant bit to 1) if this data access extension supports asynchronous calls, or to 0 if it does not. If an application attempts to make an asynchronous call to a data access extension that has the flags field cleared to 0, the Data Access Manager returns a result code of rcDBAsyncNotSupp.
Data Access Extension Parameters
This section describes the parameter block that the Data Access Manager passes to a data access extension. The section “Data Access Extension Messages” specifies which parameters are significant for each type of routine and whether each value is passed to the data access extension or returned by the data access extension.
The Data Access Manager passes a parameter block to a data access extension. The parameter block is defined as a DDEVParams record.
TYPE DDEVParams =
RECORD
message: Integer; {routine selector}
ddevStorage: LongInt; {storage for use by }
{ data access extension}
asyncPB: DBAsyncParmBlkPtr;
{pointer to asynch }
{ parameter block}
sessID: LongInt; {session ID}
returnedID: LongInt; {session ID returned}
version: LongInt; {version number}
start: LongInt; {session start time}
host: StringPtr; {name of remote system}
user: StringPtr; {user name}
password: StringPtr; {user password}
connStr: StringPtr; {connection string}
network: StringPtr; {name of the network}
buffer: Ptr; {data buffer}
err1: LongInt; {primary error code returned}
err2: LongInt; {secondary error code }
{ returned}
item1: StringPtr; {pointer to object of error }
{ message}
item2: StringPtr; {pointer to object of }
{ error message}
errorMsg: StringPtr; {pointer to error message}
timeout: LongInt; {timeout value for DBGetItem}
dataType: DBType; {data type}
sessNum: Integer; {session number}
state: Integer; {status of the data source}
len: Integer; {length of data item}
places: Integer; {decimal places in data item}
flags: Integer; {flags}
abort: Boolean {flag for DBBreak}
END;
Field Descriptions
message The routine selector that tells the data access extension which function to execute. For the values for this field and descriptions of the routines, see the next section, “Data Access Extension Messages.”
ddevStorage Reserved for use by the data access extension. The Data Access Manager sets this field to 0 when it calls the data access extension with the DBOpen message. The data access extension can store any value in this field at that time, and the Data Access Manager retains that value on all subsequent calls to the data access extension. The value of this field does not depend on the session ID; it is the same for all sessions that are using the same data access extension.
asyncPB Pointer to the asynchronous parameter block. If the application is making a synchronous call, this field is NIL. The asynchronous parameter block is described in “Asynchronous Execution of Routines” in the Data Access Manager chapter of Inside Macintosh Volume VI.
sessID The session ID. The data access extension returns the session ID to the DBInit function; all other Data Access Manager functions pass the session ID to the data access extension.
The purpose of the session ID is to provide applications with a unique identifier for each active session. The Data Access Manager reads the session ID returned by the data access extension, and then assigns a unique session ID to each session. The Data Access Manager performs the mapping between the session IDs that it provides to applications and the ones used by each data access extension.
returnedID The session ID returned by the DBGetConnInfo function.
version The version number of the data access extension assigned by the developer of the data access extension. It is not the same as the version number in the 'dflg' resource of the data access extension, which indicates the format of the data access extension.
start The time at which the session was opened, in ticks.
host The name of the remote system on which the data source is located.
user The name of the user who is establishing a session.
password The password associated with the user name.
connStr A connection string needed to establish a session.
network A string specifying the network in use for this session.
buffer A pointer to a buffer containing the item to be sent by the DBSend or DBSendItem functions or received by the DBGetItem function.
err1 The primary error code returned by the data source.
err2 The secondary error code returned by the data source.
item1 A pointer to a NULL-terminated string that identifies the first object of the error message returned by the data source. The use of this parameter depends on the specific data source you are using.
item2 A pointer to a NULL-terminated string that identifies the second object of the error message returned by the data source. The use of this parameter depends on the specific data source you are using.
errorMsg A pointer to the error message returned by the data source.
timeout The timeout period for the DBGetItem function, in sixtieths of seconds. When the data access extension executes the DBGetItem function, it requests a data item from the remote data source. If the remote data source does not return the requested data item in the amount of time specified by the timeout parameter, the data access extension should cancel execution of the DBGetItem function. The timeout value cannot be used if the DBGetItem function is called asynchronously.
dataType The data type of a requested or returned data item. Data types are described in “Getting Query Results” in the Data Access Manager chapter of Inside Macintosh Volume VI.
sessNum The session number. This number is assigned by the data access extension and is unique for all current sessions for a single data access extension only. The same session number can be assigned to concurrent sessions that use different data access extensions.
state The status of the data source.
Value Status
noErr Execution of a query successful; ready for another
rcDBValue Output data is available
rcDBError Execution of a query ended in an error
rcDBExec Currently executing a query
len The length of the data item requested or returned.
places The number of decimal places in the data item.
flags Flags returned by the DBGetItem function or sent to the DBSendItem function. For the DBGetItem function, if the flags field is set to kDBLastColFlag (that is, the least significant bit is set to 1), the data item is in the last column of the row.
There are no flags currently defined for the DBSendItem function.
abort A parameter used by the DBBreak function. The meaning of this parameter depends on the specific implementation of the data source communications system you are using.
Data Access Extension Messages
There are sixteen values that the Data Access Manager can pass to the data access extension in the messages field of the data access extension parameter block. Thirteen of them correspond exactly to the thirteen low-level functions. The other three are used by the Data Access Manager to initialize and close the data access extension and to allow the data access extension to perform routine periodic tasks. The messages that correspond to low-level routines are not described in this section. Instead, only the parameters they use and the result codes they must be able to return are listed. For descriptions of these routines, see the section “Data Access Manager Routines” in the Data Access Manager chapter of Inside Macintosh Volume VI. The DBOpen, DBClose, and DBIdle messages are described in detail in this section.
Each parameter in the list is preceded by an arrow that indicates how the parameter is used, as follows:
Æ The Data Access Manager passes the value of the parameter as input to the data access extension.
¨ The data access extension returns the value of the parameter after the routine has completed execution.
´ The Data Access Manager provides a value for the parameter, and the data access extension returns another value.
DBOpen
Parameter block
Æ 00 message word routine selector; kDBOpen
¨ 02 ddevStorage long storage for data access extension
When an application calls the DBInit function or the DBStartQuery function (which calls the DBInit function), it specifies a data access extension. If that data access extension is not already in memory, the DBInit function loads it into memory and sends it the kDBOpen message. The data access extension should allocate any memory it needs at this time. Because the data access extension can be called by more than one application, it should allocate memory in the system heap rather than the application heap. The data access extension can also return a value in the ddevStorage field of the data access extension parameter block.
When the Data Access Manager calls the data access extension, the current resource file is the data access extension file and the default directory is the Extensions Folder on the current startup disk. The data access extension must ensure that both of these values are unchanged when it returns control to the Data Access Manager.
Result codes
noErr 0 Data Access Extension initialized successfully
rcDBError – –802 Error initializing data access extension
DBClose
Parameter block
Æ 00 message word routine selector; kDBClose
Æ 02 ddevStorage long storage for data access extension
When an application calls the DBEnd function, closing the last open session for a data access extension, the Data Access Manager follows the kDBEnd message with a kDBClose message before removing the data access extension from memory. The data access extension should free any memory that it allocated before returning control to the Data Access Manager.
Result code
noErr 0 No error
DBIdle
Parameter block
Æ 00 message word routine selector; kDBIdle
´ 02 ddevStorage long storage for data access extension
The Data Access Manager periodically sends the kDBIdle message to each data access extension. The data access extension can ignore this message or take the opportunity to perform periodic tasks. Because the timing of the kDBIdle messages might not be regular, the data access extension must not depend on receiving these messages at particular times or with a particular frequency.
Result code
noErr 0 No error
DBInit
Parameter block
Æ 00 message word routine selector; kDBInit
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
¨ 10 sessID long session ID
Æ 26 host long pointer to name of remote system
Æ 30 user long pointer to user name
Æ 34 password long pointer to user password
Æ 38 connStr long pointer to connection string
The DBInit function initiates a session with a remote data source. See “Controlling the Session” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error
rcDBError –802 Error initiating session
DBEnd
Parameter block
Æ 00 message word routine selector; kDBEnd
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
The DBEnd function terminates a session with a remote data source and terminates the network connection between the application and the remote computer. See “Controlling the Session” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error
rcDBError –802 Error ending session
DBGetConnInfo
Parameter block
Æ 00 message word routine selector; kDBGetConnInfo
´ 02 ddevStorage long pointer to storage for ddev
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
¨ 14 returned ID long session ID returned
¨ 18 version long version number
¨ 22 start long session start time in ticks
¨ 26 host long pointer to name of remote system
¨ 30 user long pointer to user name
¨ 38 connStr long pointer to connection string
¨ 42 network long pointer to name of network
Æ 78 sessNum word session number
¨ 80 state word status of data source
The DBGetConnInfo function returns information about the specified session. See “Controlling the Session” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error
rcDBBadSessNum –808 Invalid session number
DBGetSessionNum
Parameter block
Æ 00 message word routine selector;
kDBGetSessionNum
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
¨ 78 sessNum word session number
The DBGetSessionNum function returns a session number. See “Controlling the Session” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error
rcDBError – 802 Error getting session number
DBKill
Parameters used
Æ 00 message word routine selector; kDBKill
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
The DBKill function cancels the execution of an asynchronous call. See “Controlling the Session” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
Æ 46 buffer long pointer to data buffer
Æ 82 len word length of data
The DBSend function sends a query or a portion of a query to the remote data source. See “Sending and Executing Queries” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error
rcDBError –802 Error trying to send text
DBSendItem
Parameter block
Æ 00 message word routine selector; kDBSendItem
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
Æ 46 buffer long pointer to data buffer
Æ 74 dataType long data type
Æ 82 len word length of data item
Æ 84 places word decimal places in data item
Æ 86 flags word flags
The DBSendItem function sends a single data item to the remote data source. See “Sending and Executing Queries” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error
rcDBError –802 Error trying to send item
DBExec
Parameter block
Æ 00 message word routine selector; kDBExec
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
The DBExec function initiates execution of a query. See “Sending and Executing Queries” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 Execution has begun
rcDBError –802 Error trying to begin execution
DBState
Parameter block
Æ 00 message word routine selector; kDBState
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
The result code returned by the DBState function indicates the status of the remote data source. See “Sending and Executing Queries” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error; ready for more text
rcDBValue –801 Output data available
rcDBError – 802 Execution ended in an error
rcDBExec –806 Currently executing query
DBGetErr
Parameter block
Æ 00 message word routine selector; kDBGetErr
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
¨ 50 err1 long primary error code
¨ 54 err2 long secondary error code
¨ 58 item1 long pointer to first object of error
message
¨ 62 item2 long pointer to second object of error
message
¨ 66 errorMsg long pointer to error message
The DBGetErr function retrieves error codes and error messages from a remote data source. See “Sending and Executing Queries” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error
rcDBError –802 Error retrieving error information
DBBreak
Parameter block
Æ 00 message word routine selector; kDBBreak
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
Æ 88 abort byte abort flag
The DBBreak function can halt execution of a query and reinitialize the remote data source, or it can unconditionally terminate a session with a data source. See “Sending and Executing Queries” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 Execution has begun
rcDBError – –802 Break or abort attempt was unsuccessful
DBGetItem
Parameter block
Æ 00 message word routine selector; kDBGetItem
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
Æ 46 buffer long pointer to data buffer
Æ 70 timeout long timeout value
´ 74 dataType long data type
´ 82 len word length of data item
´ 84 places word decimal places in data item
¨ 86 flags word flags
The DBGetItem function retrieves the next data item from the data source. See “Retrieving Results” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error; no next data item
rcDBValue –801 A nonzero data item was successfully
retrieved
rcDBNull –800 The data item was NULL
rcDBError –802 No next data item; execution ended in an error
rcDBBadType –803 Next data item not of requested data type
rcDBBreak –805 Timed out
DBUnGetItem
Parameter block
Æ 00 message word routine selector; kDBUnGetItem
´ 02 ddevStorage long storage for data access extension
Æ 06 asyncPB long pointer to asynch parameter block
Æ 10 sessID long session ID
The DBUnGetItem function reverses the effect of the last call to the DBGetItem function. See “Retrieving Results” in the Data Access Manager chapter of Inside Macintosh Volume VI for a complete description of this function.
Result codes
noErr 0 No error
rcDBError –802 Error executing function
Further Reference:
• Inside Macintosh, Volume VI, Data Access Manager chapter
NW 18 - Will Your AppleTalk Application Support Internets?
Networking M.NW.Internets
Revised by: Jim Luther July 1992
Written by: Bryan Stearns, Sriram Subramanian, and Pete Helme April 1986–April 1990
This Technical Note discusses how AppleTalk applications should work across internets, groups of interconnected AppleTalk networks. It explains the differences between life on a single AppleTalk network and life on an internet.
Changes since April 1990: Added references to AppleTalk Data Stream Protocol (ADSP) and the PPC (Program-to-Program) Toolbox and to Inside Macintosh Volume VI, and changed the section “Am I Running on an Internet?” to point out that with AppleTalk Remote Access, you can be on network zero and be connected to a remote network.
You can read about internets (AppleTalk networks connect by one or more bridges) in Inside AppleTalk. What do you need to do about them?
Use a High-Level Network Protocol
Make sure you use the Datagram Delivery Protocol (DDP), or a higher AppleTalk protocol based on DDP, like the AppleTalk Transaction Protocol (ATP), AppleTalk Data Stream Protocol (ADSP), or the PPC Toolbox. Be warned that Link Access Protocol (LAP) packets do not make it across bridges to other AppleTalk networks. Also, don’t broadcast; broadcast packets are not forwarded by bridges (broadcasting using protocols above LAP is discouraged, anyway).
Use Name Binding
As usual, use the Name-Binding Protocol (NBP) to announce your presence on the network, as well as to find other entities on the network. Pay special attention to zone name fields; the asterisk (as in “MyLaser:LaserWriter:*”) in a name you look up is now important; it means “my zone only” (see the Zone Information Protocol (ZIP) chapter of Inside AppleTalk and the AppleTalk Manager chapter of Inside Macintosh Volume VI for information on finding out what other zones exist). The zone field should always be an asterisk when registering a name.
Pay Attention to Network Number Fields
When handling the network addresses returned by NBPLookUp (or anyone else), don’t be surprised if the network number field is nonzero.
Do not assume that there are no routers on the network if your network number is zero. With AppleTalk Remote Access, you can be on network zero and be connected to a remote network. Network applications should look at the SysABridge low-memory global or use the GetZoneList or the GetBridgeAddress or the GetAppleTalkInfo calls to determine if there is a router on the network.
Watch for Out-Of-Sequence and Non-Exactly-Once Requests
Due to a “race” condition on an internet, it’s possible for an exactly-once ATP packet to slip through twice; to keep this from happening, send a sequence number as part of the data with each ATP packet; whenever you make a request, bump the sequence number, and never honor an old sequence number. If you use ADSP or the PPC Toolbox, the protocol will handle out-of-sequence packets and will always deliver data to the client in order.
Further Reference:
• Inside AppleTalk
• Inside Macintosh, Volumes II, V, VI, The AppleTalk Manager
• Technical Note M.NW.AppleTalk2Mac, AppleTalk Phase 2 on the Macintosh
• Technical Note M.NW.AppleTalk2, What’s New With AppleTalk Phase 2
NW 19 - How the Simple Network Management Protocol (SNMP) Manager Finds Network Cards
Networking
Written by: Mike Ritter June 1993
Apple provides an SNMP Manager that implements an architecture for doing network management on a Macintosh computer. This Tech Note describes how the SNMP manager finds network cards on a Macintosh and explains how you can make the SNMP Manager recognize new types of network cards. This Tech Note is a supplement to the information provided in the Developers kit for SNMP available on the E.T.O. CD-ROM in the MacSNMP Programmer’s Guide.. The kit defines the interfaces to actually gather the information.
Topics
• How the SNMP Manager finds a card’s ifGroup statistics
• How the SNMP Manager finds a card’s link layer statistics
• How to add a new card type that the SNMP Manager will understand
Introduction
This Tech Note assumes that you know something about SNMP and how it works. It also assumes that you know something about the Macintosh computer’s resource manager and driver architecture. This note provides information additional to that provided in the MacSNMP Programmer’s Guide. The method that the SNMP Manager uses to find a networking card depends on the slot manager; therefore, machines that do not support the slot manager will not support SNMP-managed network cards.
Network Management Framework
In the IETF (Internet Engineering Task Force) framework for network management there are MIBs (Management Information Bases) for practically every known device, including Ethernet cards, Token Ring cards, FDDI cards, LocalTalk, SMDS, ATM, and others. A MIB describes a minidatabase that a device must support in order to be network manageable. MIBs consist of groups, each of which contains variables and/or rows of variables (tables). One of the standard groups in the standard TCP/IP MIB II (RFC 1213) is the interfaces (if) group. The ifGroup contains variables that describe any (and every) network card. It defines statistics (identified as variables) such as number of packets sent, number of bytes sent, number of bytes received, and so on. As documented in the MacSNMP Programmer’s Guide, the SNMP Manager makes a driver call to a network card to determine this information. But how does it find the driver?
Finding the Driver
The SNMP Manager looks through all of the slots (including the pseudo slot for a .ENET0 device) using the Slot Manager. It searches for any device that has the SpBlock.spCategory set to catNetwork (=4.) It assumes that this (and only this category) is a network card. It then looks in its STR# resource (resource ID = 1) for the driver name, using the SpBlock.spCType as the index. The shipping resource is listed below.
resource 'STR#' (1,"Driver Names for cards"){
{
".ENET",".TOKN","","","","","","",
"","","","","","","","",
".FDDI"
}};
Please note that since the spCType of an FDDI card is 17, there are 14 blank entries in this resource. When the original (pre-FDDI final specifications) code for the SNMP Manager was done, FDDI was going to have an spCType of 3. It is unknown why this changed, but Apple Developer Technical Service has promised to be more compact in the future.
The reason for this hack is that the driver name for many cards is not correctly stored in the SpBlock, while the spCType always is. The SNMP Manager then checks to see if a driver of that name is opened for that slot. If it is, it can then proceed to make the parameter block based statistics calls to gather the information defined in the ifTable in the ifGroup.
The ifTable in the ifGroup is defined in ASN.1 notation in RFC 1213 as:
IfEntry ::=
SEQUENCE {
ifIndex INTEGER,
ifDescr DisplayString,
ifType INTEGER,
ifMtu INTEGER,
ifSpeed Gauge,
ifPhysAddress PhysAddress,
ifAdminStatus INTEGER,
ifOperStatus INTEGER,
ifLastChange TimeTicks,
ifInOctets Counter,
ifInUcastPkts Counter,
ifInNUcastPkts Counter,
ifInDiscards Counter,
ifInErrors Counter,
ifInUnknownProtos Counter,
ifOutOctets Counter,
ifOutUcastPkts Counter,
ifOutNUcastPkts Counter,
ifOutDiscards Counter,
ifOutErrors Counter,
ifOutQLen Gauge,
ifSpecific OBJECT IDENTIFIER
}
The SNMP Manager controls the index, as this must be the same for various other tables. Additionally, the ifTable requires that we return an object ID that describes the ifSpecific system on the card and an integer describing the ifType. This tells network management stations where to go to get information specific to this type of network card (things like how many times a Token Ring got a bad token or how many times packet length overruns occurred on an Ethernet card). The SNMP Manager finds this object identifier by using the SpBlock.spCType as the index into another resource of type ‘ifSP’. It also finds the ifType in this resource; this number is defined in RFC 1213 for several networking systems. This resources is defined as:
integer = $$Countof(OIDEnum); /* Number of specific Object IDs */
wide array OIDEnum {
unsigned long; /* ifType, from RFC 1213 */
wide array ObjectID { /* Object ID for this card type */
unsigned integer = $$Countof(ID); /* Num of IDs in OID */
wide array ID {
unsigned long; /* an ID */ };
};
};
};
And the resource that is shipping with the card looks like the following:
data 'ifSP' (1, "ifSpecific Enumerated") {
$"0011" //Three entries in table
$"0000 0006" // Enet type
$"0008" //ENET Object ID
$"0000 0001"
$"0000 0003"
$"0000 0006"
$"0000 0001"
$"0000 0002"
$"0000 0001"
$"0000 000A"
$"0000 0007"
$"0000 0009" // Token ring type
$"0008" //Token ring Object ID
$"0000 0001"
$"0000 0003"
$"0000 0006"
$"0000 0001"
$"0000 0002"
$"0000 0001"
$"0000 000A"
$"0000 0009"
$"0000 0000 0000" // #3 type + oid ID
$"0000 0000 0000" // #4 type + oid ID
$"0000 0000 0000" // #5 type + oid ID
$"0000 0000 0000" // #6 type + oid ID
$"0000 0000 0000" // #7 type + oid ID
$"0000 0000 0000" // #8 type + oid ID
$"0000 0000 0000" // #9 type + oid ID
$"0000 0000 0000" // #10 type + oid ID
$"0000 0000 0000" // #11 type + oid ID
$"0000 0000 0000" // #12 type + oid ID
$"0000 0000 0000" // #13 type + oid ID
$"0000 0000 0000" // #14 type + oid ID
$"0000 0000 0000" // #15 type + oid ID
$"0000 0000 0000" // #16 type + oid ID
$"0000 000F" // FDDI Type
$"0008" //FDDI Object ID
$"0000 0001"
$"0000 0003"
$"0000 0006"
$"0000 0001"
$"0000 0002"
$"0000 0001"
$"0000 000A"
$"0000 000E"
};
Please note again that since the spCType of FDDI is 17, there are 14 blank entries in this resource.
Both of these resources are stored in the SNMP Manager file in the Extensions folder. If you are releasing a new type of networking card and want it to be network manageable, you must perform the following steps.
To support the generic ifGroup (minimum support to claim network compatibility) you must
• implement the driver call described in the MacSNMP Programmer’s Guide for network cards; specifically, it must support the following driver selector: 242 (LapGetLinkStatus).
• ensure that the STR# resource of ID #1 in the SNMP Manager file in the Extensions folder has the name of your network driver in the correct string (the one that has an index equal to the spCType of your card).
• ensure that the ‘ifSP’ resource of ID #1 in the same place has the correct entry for your network card’s object ID. This object ID will only be used for display.
When adding your entry to either of these resources, please don’t overwrite the entire resource. Just add your specific entries to the resource. Other cards or future release may have already altered the resources beyond what is listed above and you would not want to erase useful information and cause other people’s hardware to fail.
To support the specific MIB for your network group is a bit more complicated. The shipping SNMP Manager defines a driver interface for Ethernet and Token Ring cards to use to return the network specific statistics. And future versions of the AppleTalk Connection Product will have Agents that can actually report these values to the SNMP Manager. The Agent will depend upon the correct driver name from the STR# resource described above. Thus, if you are building an Ethernet or Token Ring card you will only have to implement the correct driver calls as documented in the MacSNMP Programmer’s Guide to become fully network manageable.
If you are building a third type of card, the problem is more difficult. First the IETF has not defined MIBs for most other types of cards, and second there is no definition for which selector returns which information from the card’s driver. As new cards become available Apple may provide Link Layer agents that can manage these new cards. Apple Developer Technical Support should be notified if you are building a new card. There are several procedures to define new card interfaces, and they can recommend the best alternative for your card type.
Conclusion
Please talk to Apple Developer Technical Support if you are developing a new type of networking card for the Macintosh.
Further Reference:
• Inside Macintosh, Volume V, Slot manager
• Designing Cards and Drivers for the Macintosh Family
• MacSNMP Programmer’s Guide
• RFC 1157, A Simple Network Management Protocol
• RFC 1213, Management Information Base for Network Management of TCP/IP-Based Internets: MIB-II
• RFC 1155, Structure and Identification of Management Information for TCP/IP- Based Internets
NW 20 - PAP Status Buffer
Networking
Revised by: Jim Luther October 1992
Written by: Jim Luther (in a previous life) November 1990
This Technical Note shows the format of the ATP data part of Printer Access Protocol (PAP) OpenConnReply and Status AppleTalk response packets. A PAP client returns this information in its implementation of the PAPStatus and PAPOpen calls. The status buffer format is shown for both LaserWriter and ImageWriter (with the ImageWriter II/LQ LocalTalk Option card installed) printers.
Changes since November 1990: Much of this information originally appeared in Apple II AppleTalk Technical Note #9.
Topics
• The format of OpenConnReply and Status PAP status buffers from the LaserWriter printer and from the ImageWriter II/LQ LocalTalk Option card
• Macintosh PAP client implementation information
OpenConnReply and Status AppleTalk response packets contain up to 260 bytes of data in the ATP data part of the packet. Implementations of PAPStatus and PAPOpen calls typically return this information into an application supplied “status buffer.” In a Status packet, the first 4 bytes of the status buffer are unused. The first 4 bytes of an OpenConnReply packet’s status buffer contain the ATP responding socket number, the flow quantum from the printer or print server, and a result code. So, in either packet format, the actual “status data” starts at offset $04 in the status buffer.
The LaserWriter printer returns its status data in the form of a Pascal string. That string is usually something almost suitable to display on the screen (for example, “status: idle” or “job: Fred; document: My LaserWriter is on fire; status: busy; source: AppleTalk”). The status text displayed in the LaserWriter Driver dialog boxes is a result of the information contained in the statusString; it is not the statusString returned by PAPStatus or PAPOpen. Figures 1 and 2 show the format of the ATP data part of the Status and OpenConnReply packets returned by a LaserWriter.
Figure 1—The Status Packet From a LaserWriter
Figure 2—The OpenConnReply Packet From a LaserWriter
The ImageWriter II/LQ LocalTalk Option card does not return a status string. Instead, it returns a statusBits word where each bit within that word has a specific meaning. An application can interpret the statusBits word and generate an appropriate message to display. Figures 3, 4, and 5 show the format of the ATP data part of the Status and OpenConnReply packets returned by the ImageWriter II/LQ LocalTalk Option card and the individual bit definitions of the statusBits word.
Figure 3—The Status Packet From an ImageWriter II/LQ LocalTalk Option Card
Figure 4—The OpenConnReply Packet From an ImageWriter II/LQ LocalTalk Option Card
Figure 5—The statusBits Word From an ImageWriter II/LQ LocalTalk Option Card
There are two additional things to note when interpreting the statusBits word returned by an ImageWriter II/LQ LocalTalk Option card:
• If a sheet feeder is installed (bit 14 = 1), running out of paper results in a “Paper jam error” (bit 10 = 1) instead of a “Paper out error” (bit 13).
• The ImageWriter II/LQ LocalTalk Option card has been known to randomly return all 1s in the high byte (bits 8–15) of the statusBits word. When this happens, the statusBits word is invalid and an application should repeat the PAPStatus call to get valid information.
The Information in This Note and PAP Client Implementations
This Technical Note does not show how to make PAP calls—it only shows the format of the ATP data parts of OpenConnReply and Status AppleTalk response packets as returned by LaserWriter and ImageWriter printers. This device-specific data is important to some developers, and that’s why we’re publishing it.
It’s important that you realize the PAP client driver embedded in Apple’s current LaserWriter and ImageWriter printer drivers is unsupported by Apple. That PAP driver is unsupported because Apple engineering has always reserved the right to change its implementation as well as its calling interface, and because it will not be present in the QuickDraw GX printer drivers. To run under QuickDraw GX, applications using the PAP client driver embedded in Apple’s printer drivers must be revised to use another PAP client driver.
Apple supplies a PAP client driver that can be linked with your program. You can license that driver from Apple’s Software Licensing department (AppleLink: SW.LICENSE). As an alternative to using our PAP client driver, you can write your own PAP client. This can be a time-consuming operation (depending on how versed you are with asynchronous AppleTalk programming), but it is also very unlikely to break under future systems. Several developers have done it, and it is fairly straightforward. See the Printer Access Protocol (PAP) chapter of Inside AppleTalk for details.
Further Reference:
• Inside AppleTalk, Second Edition, Chapter 10, “Printer Access Protocol”
• PostScript Language Reference Manual, Appendix D, “Apple LaserWriter”
• “Print Hints: Looking Ahead to QuickDraw GX” by Pete (“Luke”) Alexander, develop Issue 13
NW 21 - Data Servers on AppleTalk
Networking
Revised by: March 1988
Written by: Bryan Stearns April 1985
Many applications could benefit from the ability to share common data between several Macintoshes, without requiring a file server. This technical note discusses one technique for managing this AppleTalk communication.
There are four main classes of network “server” devices:
Device Servers, such as the LaserWriter, allow several users to share a single hardware device; other examples of this (currently under development by third parties) are modem servers and serial servers (to take advantage of non-intelligent printers such as the ImageWriter).
File Servers, such as AppleShare, which support file access operations over the network. A user station sends high-level requests over the network (such as “Open this file,” “Read 137 bytes starting at the current file position of this file,” “Close this file,” etc.).
Block Servers, which answer to block requests over the network. These requests impart no file system knowledge about the blocks being passed, i.e., the server doesn’t know which files are open by which users, and therefore cannot protect one user’s open file from other users. Examples of this type of server are available from third-party developers.
Data Servers, which answer to requests at a higher level than file servers, such as “Give me the first four records from the database which match the following search specification.” This note directs its attention at this type of server.
A data server is like a file server in that it responds to intelligent requests, but the requests that it responds to can be more specialized, because the code in the server was written to handle that specific type of request. This has several added benefits: user station processing can be reduced, if the data server is used for sorting or searching operations; and network traffic is reduced, because of the specificity of the requests passed over the network. The data server can even be designed to do printing (over the network to a LaserWriter, or on a local ImageWriter), given that it has the data and can be directed as to the format in which it should be printed.
ATP: The AppleTalk Transaction Protocol
ATP, the assured-delivery AppleTalk Transaction Protocol, can be used to support all types of server communications (the LaserWriter uses ATP for its communications!). Here is a possible scenario between two user stations (“Dave” and “Bill”) and a data server station (“OneServer”, a server of type “MyServer”). We’ve found that the “conversational” analogy is helpful when planning AppleTalk communications; this example is therefore presented as a conversation, along with appropriate AppleTalk Manager calls (Note that no error handling is presented, however; your application should contain code for handling errors, specifically the “half-open connection” problem described below).
Establishing the Connection
Each station uses ATPLoad to make sure that AppleTalk is loaded. The server station, since it wants to accept requests, opens a socket and registers its name using NBPRegister. The user stations use NBPLookUp to find out the server’s network address. This looks like this, conversationally:
Server: “I’m ready to accept ATPLoad Opens AppleTalk
requests!” OpenSocket Creates socket
NBPRegister Assigns name to socket
ATPGetRequest queue a few asynchronous
ATPGetRequest calls, to be able to handle several
ATPGetRequest users
Dave: “Any ‘MyServers’ ATPLoad Opens AppleTalk
out there?” NBPLookup look for servers, finds OneServer
Dave: “Hey, MyServer! What ATPRequest Ask the server which socket to
socket should I talk to you use for further communications
on?”
Bill: “Any ‘MyServers’ ATPLoad Opens AppleTalk
out there?” NBPLookup look for servers, finds OneServer
Bill: “Hey, MyServer! What ATPRequest Ask the server which socket to
socket should I talk to you use for further communications
on?”
Server: “Hi, Dave! Use Socket N.” ATPOpenSkt Get a new socket for talking to Dave
ATPResponse Send Dave the socket number
ATPGetRequest Replace the used GetRequest
Server: “Hi, Bill! Use socket M.” ATPOpenSkt Get a new socket for talking to Bill
ATPResponse Send Bill the socket number
ATPGetRequest Replace the used GetRequest
From this point on, the server knows that any requests received on socket N are from Dave, and those received on socket M are from Bill. The conversations continue, after a brief discussion of error handling.
Half-Open Connections
There is a possibility that one side of a connection could go down (be powered off, rebooted accidently, or simply crash) before the connection has been officially broken. If a user station goes down, the server must throw away any saved state information and close that user’s open socket. This can be done by requiring that the user stations periodically “tickle” the server: every 30 seconds (for example) the user station sends a dummy request to the server, which sends a dummy response. This lets each side of the connection know that the other side is still “alive.”
When the server detects that two intervals have gone by without a tickle request, it can assume that the user station has crashed, and close that user’s socket and throw away any accumulated state information.
The user station should use a vertical-blanking task to generate these tickle requests asyncronously, rather than generating them within the GetNextEvent loop; this avoids problems with long periods away from GetNextEvent (such as when a modal dialog box is running). This task can look at the time that the last request was made of the server, and if it’s approaching the interval time, queue an asynchronous request to tickle the server (it’s important that any AppleTalk calls made from interrupt or completion routines be asynchronous).
If a user station’s request (including a tickle request) goes unanswered, the user station should recover by looking for the server and reestablishing communications as shown above (beginning with the call to NBPLookUp).
More information about half-open connections can be found in the Printer Access Protocol chapter of Inside LaserWriter, available from APDA.
Using the Connection
The user stations Dave and Bill have established communications with the server, each on its own socket (note that the user stations have not had to open their own sockets, or register names of their own, to do this—the names we’re using are merely for explanational convenience). They are also automatically tickling the server as necessary.
Now the user stations make requests of the server as needed:
Bill: “I’d like to use the sales ATPRequest Bill opens a database.
figures for this year.”
Server: “Ok, Bill.” ATPResponse The server checks to make sure that
no one else is using that database.
Dave: “Hey, Server - I’m still here!” ATPRequest Dave notices that the interval time is approaching, and makes a tickle
request.
Server: “Ok, Dave.” ATPResponse The server resets its “last time I heard from Dave”.
Bill: “Please print the figures ATPRequest Bill asks for specific data.
for January thru June.”
Server: “Ok, Bill.” ATPResponse The server does a database search
sorts the results, and prints them
on a local Imagewriter.
Dave: “I’d like to use the sales ATPRequest Dave opens a database.
figures for this year.”
Server: “Sorry, Dave, I can’t do that. ATPResponse The server finds that Bill is using that
Bill is using that database.” data.
Closing the Connection
The user stations continue making requests of the server, until each is finished. The type of work being done by the server determines how long the conversation will last: since the number of sockets openable by the server is limited, it may be desirable to structure the requests in such a way that the average conversation is very short. It may also be necessary to have a (NBP named) socket open on the user station, if the server needs to communicate with the user on other than a request-response basis. Here is how our example connections ended:
Dave: “Thank you, server, I’m done ATPRequest Dave tells the server he’s finished.
now. You’ve been a big help.”
Server: “Ok, Dave. Bye now.” ATPResponse T the server kisses Dave goodbye.
ATPCloseSkt After the Response operation completes, the server closes
the socket Dave was using. It also ATPCloseSkt notices that Bill hasn’t sent a request
in more than two intervals, and closes Bill’s socket, too.
The user station can forget about the socket it was using on the server; if it needs to talk with the server again, it starts at the NBPLookUp (just in case the server has moved, gone down and come up, etc.).
Further Reference:
• The AppleTalk Manager Inside LaserWriter
NW 22 - SNMP Transports
Network
Written by: Mike Ritter and Vincent Lubet June 1993
This Technical Note explains how to write an SNMP (Simple Network Management Protocol) Transport. An SNMP Transport is responsible for communicating between the SNMP Manager and a particular network layer. Thus, if you were writing a new network stack for the Macintosh and wanted it to use the SNMP Manager, you would write an SNMP Transport for your network stack.
Topics
• Creating and initializing an SNMP Transport
• Reading and Writing SNMP Packets
Introduction
It is assumed in this document that you understand MacSNMP, object-oriented programming and the Shared Library Manager. The SNMP Manager is built using the Shared Library Manager and is a set of shared libraries. The SNMP Manager shared library contains the implementation of the base class for an SNMP Transport. Your transport must be a subclass of this SNMP Transport class. For more information on MacSNMP and the Shared Library Manager see the E.T.O. CD ROM.
This Tech Note provides some additional information needed to construct an SNMP Transport for a particular network stack. An SNMP Transport is required to know about all of the specific idiosyncrasies of SNMP for a particular network stack. SNMP was originally defined to run over the TCP stack using UDP. The IETF (Internet Engineering Task Force) has also defined how to run SNMP over three other network stacks: AppleTalk, IPX, and OSI. These methods are documented by the IETF proposed standards: RFC 1419—SNMP over AppleTalk, RFC 1420—SNMP over IPX, and RFC 1418—SNMP over OSI. There is also an informational RFC draft that describes what must be defined to allow SNMP to run over any particular network stack.
Apple provides SNMP transports that support the TCP stack and the AppleTalk stack. The TCP SNMP Transport provides knowledge of IP addresses, listens on the well-known SNMP sockets, sends SNMP packets on UDP, and resolves addresses in dotted notation into IP addresses for sending Traps. (An SNMP Trap is the method that SNMP entities use to send unsolicited warning messages to each other and should not be confused with a Macintosh Operating System Trap.) The AppleTalk SNMP Transport likewise provides knowledge of AppleTalk addresses, listens on the well-known SNMP sockets, sends SNMP packets on DDP, and resolves NBP (Name Binding Protocol) names into AppleTalk addresses for sending Traps. Similarly, a new SNMP Transport would have to provide these same services: understanding the new network addresses, listening for SNMP packets, sending SNMP packets, and resolving stored console addresses to network addresses for sending Traps.
SNMP Transports
Figure 1—An SNMP Transport provides the interface between the SNMP Manager and a particular network stack.
Creating an SNMP Transport
The file Transport.h defines the SNMP Transport class. To create an SNMP Transport, you must subclass the SNMP Transport class. The Shared Library Manager allows a run-time link of your SNMP Transport subclass with the base object SNMP Transport provided in the SNMP Manager shared library. The definition of the SNMP Transport object is as follows:
To start an SNMP Transport you must instantiate it. For the AppleTalk SNMP Transport, we install a process on the AppleTalk transition queue that tells us when AppleTalk is coming up or going down and instantiate or destroy the Transport as appropriate. For the TCP SNMP Transport, an INIT31 instantiates the Transport and it is never destroyed. For your Transport you must provide the code that instantiates and destroys your Transport.
When a Transport is instantiated the base class constructor is called first. The base class constructor fills in the fSNMPManagerPtr field with a pointer to a class TSNMPManagerPrv, which can be cast to a pointer to the class TSNMPManager defined in TSNMP.h. This pointer can be used to access the members of the TSNMPManager class. The constructor also adds a pointer to your SNMP Transport object to a queue of transports so that it can find you later, and if everything worked, sets the fValid field to true. Your constructor is then called. If the fValid field is not set to true on the entrance to your constructor, you should bail out of the constructor immediately. If your constructor fails for some reason, you should set the fValid field to false. The Shared Library Manager will then clean up the object so that a partially constructed one does not remain.
Initializing an SNMP Transport
After your Transport is constructed it must be initialized. Your transport will not work until InitSNMPTransport() is called. This routine sets all of the fields in the SNMP Transport from the parameter values that you pass in. You must call the inherited InitSNMPTransport member function if you override it. The following fields must be set.
-> TransportTag aTag
A long that uniquely identifies a transport (analogous to OSType)
-> TIAddressPtr aTrapSocketPtr
Opaque address of where the Transport listens for Traps
-> TIAddressPtr aReqSocketPtr
Opaque address of where the Transport listens for Requests
-> Boolean ahandlesresolution
True if the transport can send Traps
-> short aWritebufsize
Maximum size of write buffers
-> TransportRWProcPtr aWriteProcPtr
Address of the write procedure
-> short aNumofReads
Maximum number of reads issued at once
-> short aReadTIAddrSRCmax
Maximum length of source address for read operations
-> short aReadTIAddrDESTmax
Maximum length of destination address for read operations
-> short aReadbufsize
Maximum size of a read buffer
-> TransportRWProcPtr aReadProcPtr
Address of the read procedure
The aReadProcPtr and aWriteProcPtr have the following definition:
It is recommended that the TransportTag be four human readable ASCII characters that describe the network layer that the Transport talks to. If multiple Transports with the same TransportTag are instantiated, the SNMP Manager will ignore all but the first one instantiated. For the AppleTalk SNMP Transport the tag is 'DDP ', for the TCP SNMP Transport the tag is 'UDP '. This value is used in the Trap Table in the Macintosh Agent to determine which Transport understands the console address stored in a particular row of the table. The sockets are where the Transport listens for Traps and Requests. The SNMP Manager does not understand the format of these addresses and just passes them along to your Transport. They are also used as the source of Traps or Responses sent. Finally, they allow the SNMP Manager to determine what type of packet it is decoding before parsing the raw ASN.1 data. In our Transports we have stored pointers to the actual bits of the network layer addresses in these fields. The aWritebufsize and aReadbufsize are the size of buffers that the SNMP Manager allocates for your Transport to use.
Reading SNMP Packets
Finally, InitSNMPTransport() tries to issue aNumofReads outstanding reads by calling your aReadProc() with a filled in SNMPTransportBlock as shown in Figure 2. The SNMPTransportBlock is defined as follows:
struct SNMPTransportBlock {
unsigned long qLink; // reserved for pointer to next block
short qType; // reserved for queue routines
TSNMPTransport* transport; // who was asked to read or write block
SNMPError result; // after request is serviced
void* destopaqueData;// destination address to be resolved (used in write trap only)
TIAddressPtr destination; // who the packet was sent to
TIAddressPtr source; // who sent the packet to us
void * UserDataPtr; // Transport work space
Boolean freeFlag; // is the write finished?
Boolean readFlag; // managed by SNMP Manager
PacketElementPtr pktelementPtr;// managed by SNMP Manager
SNMPPacketStructPtr packetPtr; // managed by SNMP Manager
};
The aReadProc() must be able to catch both incoming Traps and Requests. It must also be able to be called at any time, thus you must not allocate memory using the normal Macintosh memory calls. You may use the area pointed to by UserDataPtr for any scratch you might need. The SNMP Manager has preallocated this area for you according to the sizes you set in aReadbufsize. It must also return immediately. When a read actually completes you must call SNMPReadDone() after filling in the data, the source and destination addresses, the actual number of bytes read (in packetPtr->packetPiece.dataSize), the freeFlag (set to false), and the result (snmpNoError if it worked.)
Warning: If the freeFlag is incorrectly set, the SNMP Manager will become hopelessly confused.
After the read packet is processed by the SNMP Manager it issues another read call to aReadProc() so that there will always be some number of outstanding reads. If there are no outstanding reads at any time it is allowable for your transport to drop SNMP packets.
Figure 2—Layout of SNMPTransportBlock when aReadProc() called. Only the fields that the Transport may need to access are shown.
When your Transport is deleted you must ensure that your completion routines will not be called after your destructor is finished and your Transport object is gone. You may have to wait for asynchronous writes to complete and cancel any outstanding reads. The base class destructor will ensure that any packets you have queued up for processing will be thrown away.
Figure 3—Layout of SNMPTransportBlock when the SNMP Manager calls aWriteProc() with a response to an SNMP Request.*
*Only the fields that the Transport may need to access are shown.
Writing SNMP Packets
After a packet is processed by the SNMP Manager, it will almost always generate a Response packet. The SNMP Manager will either respond to a Request or generate a Trap. In the cases of a simple Response the SNMP Manager will call your aWriteProc() with an SNMPTransportBlock filled out as shown in Figure 3. Your aWriteProc() may be called at any time, thus you must not allocate memory using the normal Macintosh memory calls. You may use the area pointed to by UserDatPtr for any scratch memory you need. The SNMP Manager has preallocated this area for you according to the sizes you set in aWritebufsize. The destination socket is the same block as was passed in on the read as the source socket, the source socket is your initialized fRequestSocketPtr, the packetPtr points to the SNMP data to put on the wire. You must return immediately from the call to aWriteProc(). After the write completes you should fill in the result, set the freeFlag to true, and call SNMPWriteDone() so that the SNMP Manager can free up the memory it allocated.
Warning: If the freeFlag is incorrectly set the SNMP Manager will become hopelessly confused.
If your Transport can send Traps it must set the fHandlesResolution field to true. It is strongly encouraged that your transport handle Traps, if it did not, it would not be fully compliant with the SNMP standard. When a Trap is generated, the SNMP Manager will determine if the Trap is supposed to be sent to a console that supports your Transport type by looking through the Trap table in the Macintosh System MIB implemented by the Macintosh Agent. If so, it will issue a call to your aWriteProc() as above, except that the destOpaqueData will point to a block that the SNMP Manager has procured from the trapDestination field in the Trap Table in the Macintosh Agent. It is up to you to define how this address will be stored. However, it must be nonvolatile between reboots of the system. For the AppleTalk SNMP transport, we store the NBP name of the console as specified in the AppleTalk over SNMP RFC. For the TCP SNMP Transport, we store the IP address of the console in dotted notation The Transport is responsible for turning this address into the wire address of the console. Everything else is as above. You must return immediately after the call to your aWriteProc() and call SNMPWriteDone() when the Trap write completes.
The Trap Table is implemented by the Macintosh Agent and is defined in ASN.1 by the Macintosh System MIB as:
TrapRequestEntry ::= SEQUENCE {
trapIndex INTEGER, // unsigned long
trapCommunity MacintoshDisplayString, // opaque data
trapProtocol MacOSType, // four bytes
trapDestination OCTET STRING, // opaque data
trapValidity INTEGER // 1 = valid, 2 = invalid
}
The two fields that an SNMP Transport author must define are the trapProtocol and the trapDestination. The trapProtocol is compared by the SNMP Manager to the TransportTag and is used to identify which SNMP Transport will be able to resolve the trapDestination entry and send the Trap. The trapProtocol field must contain the same value that was initialized in the transportTag field. Some care should be given to the format of the trapDestination as network managers will have to enter these addresses by hand from a console.
Summary
An SNMP Transport provides an interface between the SNMP Manager and a network layer of a particular network stack. It must be able to be called at any time, thus cannot depend on the Macintosh memory calls. A Transport must understand how a Trap destination (console address) is to be stored in the Macintosh Agent’s Trap Table. This address format must be stable between reboots of the system and must be resolvable into a network address for the console. It is the responsibility of the Transport developer to inform network managers of how to store this address. For IPX, AppleTalk, and OSI, these standards have been specified in RFCs (Request For Comments). These documents are available on-line off of the Internet and are maintained in various repositories and formats by the IETF.
Further Reference:
• MacSNMP Programmer’s Guide
• Shared Library Manager Programmer’s Guide
• RFC 1157, A Simple Network Management Protocol (SNMP)
• RFC 1155, Structure and Identification of Management Information for TCP/IP-based Internets
• RFC 1419, SNMP over AppleTalk, Internet Proposed Standard
• Macintosh System MIB
NW 23 - Routes From the Source
Networking
Written by: Tim Enwall and Rich Kubota January 1992
This Technical Note discusses source routing and its possible implementation in token ring link layers.
Introduction
“AppleTalk,” in the words of Gursharan Sidhu, “is a network system.” As such, it provides for multiple types of media and data links, and token ring is one such data link.
Source routing refers to a process on token ring networks where the source of a packet indicates, to any bridges between the source and the destination, the route a packet must take to get from the source to the destination. The destination also uses this same route to transmit the response packet back to the proper place. The presence of routing information is indicated by a 1 in the most significant bit (MSB) of source address (SA) filed in the media access control (MAC) header. For nodes on the same ring, note that routing information is unnecessary.
Broadcast packets on a token ring always have their routing information bit turned on (Figure 1), indicating to bridges between the source and destination nodes that the route is to be inserted into the packet. For non-broadcast packets, each source node (SN) determines whether routing information is necessary, and hence either puts a 1 into the MSB of the source address and appends the routing control field, or it doesn’t. If the source routing bit is set to one, the routing information field (RC) is inserted between the source address (SA) field and the information field. With the source routing bit set to 0, the information field would immediately follow the source address (SA) field.
Each bridge puts its adjoining segment number into the next available SN field in the routing information field. Thus, a destination node could receive multiple packets from multiple bridges, and thus have several routes back to the source.
Note: The term broadcast here refers to link-level broadcasts. This is not to be confused with AppleTalk broadcasts to the AppleTalk address $FF. These types of broadcasts are destined only for AppleTalk nodes on the link, not necessarily all nodes on the link.)
Figure 1 Routing Information and Routing Control Fields
Types of Broadcasts
At present, packets can be broadcast in one of three ways. The type of broadcast is defined by three bits in the routing control field of the routing information field (see Figure 1).
The types of broadcasts are as follows:
100 All-routes broadcast, non-broadcast return. Broadcast packets of this type will travel along any possible path to the destination; thus the number of packets received at the destination will equal the number of routes to the destination node. Packets coming back to the source will travel along the same route, in reverse order, as they did going to the destination.
110 Single-route broadcast, all-routes broadcast return. Broadcast packets of this type will travel along a single route, passing through designated bridges to the adjoining segment. Packets coming back to the source can possibly travel along multiple paths to reach the source; thus, the first packet received back at the source will indicate the best route between the destination and the source. A network administrator will set up the designated bridge as one that will forward this kind of broadcast. (Note that rev F of the TMS380 Adapter Chipset User's Guide Supplement, which describes these bits on page 7-4, incorrectly documents the bits, 111, to this type of broadcast.)
111 Single-route broadcast, non-broadcast return. Broadcast packets of this type will travel along a single route, passing through designated bridges to the adjoining segment. Packets coming back to the source will travel along the same route, in reverse order, as they did going to the destination. A network administrator will set up the designated bridge as one that will forward this kind of broadcast. (Note that rev F of the TMS380 Adapter Chipset User's Guide Supplement, which describes these bits on page 7-4, incorrectly documents the bits, 110, to this type of broadcast.)
For directed transmissions between several bridges, the broadcast bits are 000. This indicates that the route is already present in the segment numbers, and the packet travels in a directed manner to the destination.
Source Routing on Apple’s TokenTalk Card
Apple’s TokenTalk Card is built upon the Macintosh Coprocessor Platform. Much of the TokenTalk software consists of dynamic A/ROSE tasks running on the card. Developers can use the services of TokenTalk Prep (documentation of which is available on the TokenTalk NB Programmer’s Guide), and the actual source routing is done with a SNAPXmit. SNAPXmit does the exact same thing as LLCXmit, but it doesn’t do source routing for you, nor do you have to specify a service access point (SAP).
Essentially, we have two types of packets to transmit: broadcast packets and individual directed packets.
For broadcast packets, which include functional address transmissions, group address transmissions, and all-stations broadcast transmissions, we add source routing information. For TokenTalk, the broadcast type is all-routes broadcast, non-broadcast return.
For individual directed packets, we have to determine if the destination is on our ring or not. If it is not then we must append the routing information to the packet. Where does the route come from? If we’ve been smart, we’ve been gathering routes from any broadcast packet we receive, and saving them away. We want to have a couple of tables on which to store the information: a table that maps destination nodes to ring numbers (segment numbers), and a table that maps ring numbers to routes. If we are asked to transmit an individual packet, we simply look up the destination ring number (compare it with our own ring number to determine whether routing information is necessary) and then look up the route for the ring we just looked up. Once we have a match, we just append the routing information and transmit the packet. Everything’s hunky- dory.
“But,” you ask, “what if I don’t have the route?” That is, what if there’s no ring number mapped to the destination address? You'll have to find the best route and then send it along. We do this by queuing the original request momentarily, packing up a Logical Link Control (LLC) test command packet, putting the desired destination address into the packet, and setting the broadcast type to “single-route broadcast, all-routes broadcast return.” This means we’ll get back (potentially, if there’s more than one route) many responses with routes in them. Hopefully the first such packet we receive will indicate the best route because it took the shortest amount of time to reach us.
Now, you’re probably asking yourself: “What did you mean when you said, ‘If we’ve been smart, we’ve been gathering routes from any broadcast packet we receive’?” Even better, every TokenTalk packet broadcast at the link layer will have this source routing information in it. Therefore, every TokenTalk packet will contain the route back to the source and we can “glean” this information and store it in our tables. This is where the direction bit comes in handy. If the direction bit is 1, then the furthest segment is the last segment number in the routing information field, that is, the rightmost. Conversely, if the direction bit is 0, then the furthest segment is the first segment number in the routing information field, that is, the leftmost. This furthest segment indicates the ring number the source is actually on, and we can add this source ring number to our table. We can also add (or update) our ring number to route table.
“What if the entries in this table just sit around—potentially after a node is no longer reachable?” That’s a good question. Again, we’ll use a common practice for such tables: each entry in our table should have some “age” associated with it, and when the “age” gets too old, we delete the entry from our table. The worst thing that can happen from such a deletion is we’ll have to go through the route discovery process again.
Conclusion
Source routing is necessary for any token ring link to function. Thus, hopefully, you have a clear recipe here for implementing that functionality in your code.
• J. Scott Haugdahl: Inside the Token-Ring, Chapter 3, “Standards and Protocols”, Architecture Technology Corporation, 1986
NW 25 - TokenTalk Programmer’s Guide Update
Networking
Written by: Rich Kubota July 1992
This Technical Note presents the additions and changes to the TokenTalk Programmer’s Guide and the latest information with regard to software development for the Apple Token Ring NB and Token Ring 4/16 NB network cards.
Introduction
With the release of the Token Ring 4/16 NB Card, the TokenTalk driver software was modified to support the Multivendor ADEV Architecture. This architecture is described in detail in M.NW.AppleTalk2, “What’s New With AppleTalk Phase 2.” This Tech Note presents topics specific to TokenTalk as presented in the TokenTalk Programmer’s Guide.
The first section, “TokenTalk Prefs File,” discusses changes to the 'llcp' resources of the TokenTalk Prefs file. The Options field is now used to store the speed setting for the card and to determine whether the Early Token Release feature is to be supported.
The next section, “TokenTalk Prep Services,” describes the new TokenTalk Prep utility routines for getting and setting the default and boot parameters for an Apple MCP (Macintosh Coprocessor Platform) based token ring network card.
Getting the Latest TokenTalk Software
For testing purposes, the latest version of AppleTalk and related software can be installed by using the Network Software Installer, available on the latest Developer CD, on AppleLink on the Developer Services Bulletin Board, and on the Internet through anonymous FTP to ftp.apple.com (130.43.2.3). The Network Software Installer includes all necessary components for the TokenTalk driver software including A/ROSE.
TokenTalk Prefs File
This section discusses the changes to the 'llcp' resource and supplements the material presented in Chapter 6, “Download and Initialization” of the Programmer’s Guide. The primary change to the resource concerns the 'Options' field, and the increase of the default MaxFrame size setting. The TokenTalk Prefs file will be found in the Preferences folder in system software version 7.0 and later, and in the System Folder for version 6.0.x. The file contains the preferred Logical Link Control (LLC) initialization parameters for a card. These parameters are stored in 'llcp' resources with resource IDs corresponding to the slot number of the smart Token Ring Card to be supported. These initialization parameters override the default settings provided in the TokenTalk Prep file. For example, if the user selects a smart Token Ring Card in NuBus slot 9 to be used, the TokenTalk Prep routines will search for 'llcp' resource ID 9 in the Prefs file. If the resource is not found in the Prefs file, the default 'llcp' parameters in the Prep file will be used.
The format of the 'llcp' is as follows:
typedef struct
{
long FAddr; /* Functional address */
long GAddr; /* Group address */
long Options; /* See below */
void (*Listener)(); /* Pointer to SAP 0 listener, always 0 in resource */
unsigned short MaxFrame; /* Maximum frame size */
unsigned short StationMax; /* Maximum number of stations */
unsigned short BufferSize; /* Buffer size within chipset */
unsigned char SAPMax; /* Maximum number of SAPs */
unsigned char GSAPMax; /* Maximum number of GSAPs */
unsigned char GSAPMemberMax; /* Maximum number of members in a group SAP */
unsigned char TxBufs; /* Number of buffers in transmit list */
unsigned char RxBufs; /* Number of buffers in receive list */
unsigned char IntMsgs; /* Number of interrupt message buffers */
unsigned char TimerT1_1; /* Default group 1 response timer */
unsigned char TxBufMax; /* Transmit buffers maximum */
unsigned char NodeAddr[6]; /* Node address (0 to use burned-in address) */
unsigned char ProdID[18]; /* Product ID string */
unsigned char LLCName[32]; /* IPC name of this LLC (C string) */
} TRInit;
Options Field
TokenTalk version 2.4 makes use of the low three bits of the Options field as follows:
Bits 0 and 1 are used to indicate the current speed setting for the Token Ring 4/16 NB Card as follows:
4 Mbits/sec bit 0 -> ON, bit 1 -> OFF
16 Mbits/sec bit 0 -> OFF, bit 1 -> ON
Bit 2 is used to flag use of the “Early Token Release” feature : 0 -> ON, 1 -> OFF. This feature only applies to the TokenRing 4/16 NB card when operating at 16 Mbits/sec.
For speed switchable cards, the TokenTalk Phase 2 ADEV checks whether bits 0 and 1 have been set correctly when the user selects a smart card in the network cdev. If neither bit is set, the user is presented with a dialog box allowing the user to select the desired speed. The Token Ring cdev also checks these bits to determine which radio button to select for speed switchable smart cards. For the TokenTalk NB card, which is nonswitchable, the bit settings are insignificant, and the speed is assumed to be 4 Mbits/sec.
Default Maximum Frame Size
The default MaxFrame size setting in TokenTalk version 2.3 and earlier was 1536 bytes. With TokenTalk Prep version 2.4, the maximum default frame size has been increased to 4464 bytes. The maximum frame size setting limits the amount of memory set aside by the token ring chipset for each receive buffer. If on an LLCOpenSAP or LLCOpenStation call, the MaxIField setting is greater than the MaxFrames value specified in the 'llcp' resource, then the MaxFrame value is used instead.
TokenTalk Prep Services
TokenTalk Prep version 2.4 provides several new services to developers for determining and setting boot time parameters, and determining whether the Token Ring Card is speed switchable. The following new selectors are implemented in the TokenTalk Prep 'ttut' utilities. This section supplements the material presented in Chapter 6, “Download and Initialization,” of the Programmer’s Guide.
TTGetBootParms 11 Return TRInit parameters to use at the next boot time.
TTSetBootParms 12 Save TRInit parameters to the TokenTalk Prefs file.
TTSpeedSwitchable 13 Determine if the token ring speed is switchable or not.
TTGetDefaultParms
The TTGetDefaultParms function returns a pointer to the default LLC initialization parameters from the TokenTalk Prep file 'llcp' resource. The second parameter to this request is a mask of the slot to operate on. This mask must have only a single bit set since the default parameters for a single card can be returned. The result of this operation is a 32-bit NuBus address, a pointer to a structure of type TRInit, if nonzero. The pointer must be disposed of when finished.
This function calls a card-specific routine to fill in the address field with that of the burned-in address from the card, the Product ID string, and the LLCName as a C string. A result of 0 indicates that
1. there is no supported card in the specified slot,
2. more than one card was specified,
3. the 'llcp' resource could not be found,
4. or a memory allocation error occurred.
The following call returns the default LLC parameters for a smart Token Ring Card in NuBus slot C:
result = (*UtilPtr) (TTGetDefaultParms, 1<<0xC);
TTGetBootParms
The TTGetBootParms function returns a pointer to the LLC initialization parameters to be used on the next boot of the designated card. As with the TTGetDefaultParms function, the second parameter to this request is a mask of the slot to operate on. This mask must have only a single bit set. This function first checks whether a card-specific 'llcp' resource for the card exists in the TokenTalk Prefs file; otherwise the default parameters specified in the 'llcp' resource in the Prep file are returned. The result of this operation is a 32-bit NuBus address, a pointer to a structure of type TRInit, if nonzero. The pointer must be disposed of when finished.
This function calls a card-specific routine to fill in the address field with that of the burned-in address from the card, the Product ID string, and the LLCName as a C string. A result of 0 indicates that
1. there is no supported card in the specified slot,
2. more than one card was specified,
3. an 'llcp' resource could not be found,
4. or a memory allocation error occurred.
The following call returns the default LLC parameters for a smart Token Ring Card in NuBus slot D:
result = (*UtilPtr) (TTGetBootParms, 1<<0xD);
TTSetBootParms
The TTSetBootParms function stores LLC initialization parameters to the TokenTalk Prefs file. The function takes as input a pointer to a structure of type TTSetBP as the second parameter. The structure type, TTSetBP, is described below. The function searches for the Prefs file in the Preferences folder or creates the file if one does not exist. It then writes the initialization parameters to an 'llcp' resource using the slot number passed in the TTSetBP parameter block. If an 'llcp' resource already exists under the ID of the slot number, the old resource is replaced by the new parameters. The function returns TRUE if the parameters are successfully stored, or FALSE if unsuccessful. Under system software version 6.0.x, the Prefs file is searched for or created in the Blessed Folder.
The newly stored LLC initialization parameters will be used the next time the card is started. To use the burned-in address on the card as the node address of the card, set all bytes of the NodeAddr field to 0.
A result of 0 indicates that
1. a memory allocation error occurred,
2. a problem occurred opening the Preferences folder or file,
3. the Prefs file could not be created,
4. or Resource Manager error occurred.
typedef struct
{
long SlotNo; /* Slot number to save */
TRInit *TRPtr; /* Pointer to a TRInit data structure described above */
} TTSetBP;
The following demonstrates the use of the TTGetBootParms utility to set the boot parameters for a smart Token Ring Card in NuBus slot E:
TRInit myTRRec;
TTSetBp my SetBP
void *SetMyTRInitRec(TRInit &myTRRec);
SetMyTRInitRec(myTRRec); /* set LLC parameters */
mySetBP.SlotNo = 0x0E;
mySetBP.TRPtr = myTRRec;
result = (*UtilPtr) (TTGetBootParms, &mySetBP, );
TTSpeedSwitchable
The TTSpeedSwitchable function returns true if the speed on the Token Ring Card can be switched, or false if not. This function does not indicate the current speed setting for the card. To determine the speed, check the Options field of the 'llcp' resource. If the two lowest bits, 0 and 1, are not set, then assume that the card supports only the 4 Mbits/sec speed. The second parameter to this request is a mask of the slot to operate on. This mask must have only a single bit set since the setting for only a single card can be returned.
The following call returns the default LLC parameters for a smart Token Ring Card in NuBus slot A:
result = (*UtilPtr) (TTSpeedSwitchable, 1<<0xA);
Further Reference:
• TokenTalk Programmer’s Guide, Apple Computer, Inc. (M0827LL/A)
• M.NW.AppleTalk2
• Macintosh Coprocessor Platform Developer's Kit, Apple Computer, Inc. (M0793LL/A)
NW 505 - AppleTalk Data Stream Protocol Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
AppleTalk Data Stream Protocol references
Date Written: 11/13/90
Last reviewed: 8/1/92
Where are the AppleTalk Data Stream Protocol (ADSP) calls documented?
___
APDA has a product called “ADSP: AppleTalk Data Stream Protocol Development Kit” that gives you ADSP and the ADSP call descriptions. ADSP and ADSP interfaces can be found on the Developer CD and can be used for your development purposes. However, you’ll need to license ADSP through Apple Software Licensing (AppleLink: SW.LICENSE) before you ship your product. Calls are also documented in Chapter 32 of Inside Macintosh Volume VI.
If you want to use ADSP, then you should read ALL of the documentation. There are various tips and explanations that may be vital to your implementation of ADSP in your product. It is useful for transferring data between machines and provides built-in error checking to ensure that you do receive the data at the other end. For these reasons, you should read Inside AppleTalk, Chapter 12, Apple Data Stream Protocol, to make sure you utilize it to its fullest.
Sending broadcast packets to transmit data to multiple clients
Date Written: 11/19/90
Last reviewed: 6/14/93
How do I broadcast information over AppleTalk using the Communications Toolbox (CTB) and the AppleTalk Data Stream Protocol Development (ADSP) Tool or multiple access? I cannot find any significant information regarding broadcast or multiple access transmissions.
___
There is no supported method to send broadcast packets to transmit data to multiple clients. The reason is that this method does not ensure the data was received by every client. It is possible to lose a packet on a network before it reaches a client even though it may reach the others. If this is the case then the data is lost forever for this client unless you resend the packet. This is highly inefficient and unreliable.
If you want to have multiple clients, then you’ll need to write your own server software that can handle multiple clients logged on simultaneously. The server will then need to keep a record of every connection and its corresponding transaction ID even though you will be sending the same information to each client; this is to ensure that each client receives the data. Following the ADSP protocol should be enough for you to implement this server/client connection and ensure that the data is reliably transmitted to each node.
ADSP closes connections on eClosed or eTearDown events
Date Written: 7/30/91
Last reviewed: 6/14/93
When I receive an eClosed or eTearDown ADSP connection event, do I have to close my end of the connection, or does ADSP close it automatically?
___
When you get a eClosed unsolicited event, it means the other (remote) side of the ADSP connection sent a Close Connection Advice control packet and ADSP has closed the connection. It is purely advisory and does not require you to take any action. The Close Connection Advice control packet allows ADSP to close connections faster than just waiting for the connection to time-out due to the open timer expiring.
When you get a eTearDown unsolicited event, it means the network connection with other side of the ADSP connection was lost (the open timer expired) and ADSP has closed the connection. Again, it is purely advisory and does not require you to take any action.
The ADSP chapter of Inside AppleTalk (Chapter 12) might with help other questions you may have about ADSP in the future since it explains how ADSP works beneath the Macintosh implementation documented in Inside Macintosh Volume VI.
ADSP dspAttention and attention retransmit timer interval
Date Written: 9/16/91
Last reviewed: 6/14/93
I’m having problems with the AppleTalk Data Stream Protocol (ADSP) call dspAttention. Sometimes it takes several minutes for dspAttention to complete.I’ve tried using ADSP 1.5.1 with System 6.0.7 and ADSP 56, which ships as part of System 7.
___
ADSP 1.5.1 (and ADSP 56) no longer uses the attnInterval field in the DSPParamBlock for the attention retransmit timer interval. Instead, the attention retransmit timer interval is based on the round-trip time of ADSP data packets. When a connection end is established, the attention retransmit acknowledged, the attention retransmit timer interval is adjusted for the connection speed. This mechanism works well when a connection end is established, an ADSP connection is opened, the connection is used, the connection is closed, and then the connection is eliminated.
A problem in this mechanism can surface when a connection end is established and is reused over and over for several ADSP connections. When a connection is closed and then a new connection is opened using the same connection end, the attention retransmit timer interval is not reset to the default starting value (the problem). Instead, some garbage value in memory is used. If the first ADSP attention packet or the acknowledgment packet returned for that attention packet is lost on the network, ADSP will use the “garbage” value for the attention retransmit timer interval and it could take several minutes for ADSP to retry sending the attention packet.
This has been fixed for versions of ADSP greater than version 56. With versions of AppleTalk 56 and earlier, the only workaround is to use a new connection end for every new ADSP connection requiring ADSP’s attention mechanism.
Using ADSP with AppleTalk for Apple’s VMS
Date Written: 5/3/89
Last reviewed: 6/14/93
I am trying to create a simple program to try ADSP (AppleTalk Data Stream Protocol) with AppleTalk for Apple’s VMS (version 2). I started the bridge process but got an access violation on the first call.
___
You need to make three calls before you can call any other functions with AppleTalk for VMS. These calls are:
ATK$INIT_ATALK
ATK$INIT_PORT
ATK$OPEN_PORT
Then you can use the other routines.
Appletalk Internet Router and Internet Protocol support
Date Written: 5/15/92
Last reviewed: 8/1/92
Does the Appletalk Internet Router support the routing of Internet Protocol packets, or Datagram Delivery Protocol-to-Internet Protocol translation?
___
The AppleTalk Internet Router does not provide support for routing IP packets or the translation of IP packets encapsulated inside AppleTalk packets into IP packets. It only supports the routing of AppleTalk packets between AppleTalk link layers such as LocalTalk, EtherTalk, and TokenTalk. To route IP packets between, for instance, a LocalTalk network and an IP only backbone, you'll need to purchase a hardware router such as a Cayman Gatorbox or a Shiva Fastpath. Using one of these routers you can, using MacTCP, tunnel IP packets in AppleTalk packets by selecting the appropriate AppleTalk adev from within the MacTCP Control Panel. This will allow transfer of IP packets over the wire and the hardware routers will then strip the AppleTalk protocol, allowing IP packets to reach their destination over Ethernet. In addition, these routers usually support tunneling AppleTalk within IP packets (IPTalk).
If both the host computer running the TCP/IP protocol stack and the Macintosh you wish to connect from are on the same Ethernet wire, you can select Ethernet from the MacTCP Control Panel to bypass the encapsulation of IP packets within AppleTalk DDP packets.
ADSP session limits
Date Written: 7/21/92
Last reviewed: 6/14/93
What’s the absolute maximum number of ADSP sessions that a single Macintosh can have? What’s the largest client community that can be served at any given time?
___
As documented in Inside AppleTalk 2nd Edition, page 4-5, dynamic sockets can range from 128-254. Therefore, when using ADSP you have 126 different dynamic sockets available for use as connection ends.
Note that you may have only one connection open between a pair of sockets. However, it is possible to have multiple connections open on the same socket, provided that the other end of each connection resides on a different socket. For example, socket 128 on machine B may have connections with socket 128 on machine C and socket 128 on machine D, but it may not have more than one connection with the same socket of a remote machine.
When a connection is established between two sockets, each connection end is assigned a unique connection ID value (ConnID). The ConnID is an unsigned integer. Therefore, it is theoretically possible to have 65,535 different connections on a single machine.
However, since each connection requires that you allocate a CCB data structure (242 bytes), you will most likely run out of memory long before this limit is reached. In addition, the more connections you have, the more traffic you will generate on the network since each connection is maintained internally by ADSP with probe control packets and connection timers (see Chapter 12 of Inside AppleTalk 2nd Edition for the details). On top of that, if each connection is transferring a lot of data, the burden of passing ADSP packets around will put an even greater strain on your machine and the network in general.
NW 510 - AppleTalk Filing Protocol Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As in this Technical Note:
AFP error codes -5060,-5061, -5062, and -5063
AFP error codes -5060,-5061, -5062, and -5063
Date Written: 1/18/93
Last reviewed: 6/14/93
What’s AppleTalk error -5062? It seems to be an AppleTalk Filing Protocol error of sorts but I can’t find it documented anywhere.
___
Error -5062 is an afpAlreadyMounted error. You’ll get it from the AppleShare external file system if you try to mount an AppleShare volume that’s already mounted with PBVolumeMount. The three PBVolumeMount-related functions were added to System 7 very late during development, so afpAlreadyMounted (-5062), afpBadDirIDType (-5060), afpCantMountMoreSrvrs (-5061), and afpSameNodeEr (-5063) never made it into the public interface files.
Further Reference:
Inside Macintosh Volume VI, pages 25-49 and 25-50
How an AFP volume’s allocation block size is calculated
Date Written: 8/15/91
Last reviewed: 8/16/91
The AppleTalk Filing Protocol (AFP) doesn’t appear provide a way to learn about the allocation block size of a server volume. So, how is the allocation block size determined on AFP server volumes? I noticed that the Macintosh Finder seems to calculate “size on disk” erratically for files on some AFP server volumes. Is that a related problem?
___
All the workstation can get from an AFP server is the Bytes Total and Bytes Free (returned by FPGetVolParms and FPOpenVol), so the AFP workstation code estimates the value it uses in the allocation block size field (vcbAlBlkSiz) of the volume control block (VCB). The workstation code comes up with a value for vcbAlBlkSiz from the Bytes Total value returned to FPOpenVol when the volume is opened. The calculation used is:
This is the same value a local HFS volume would use. If an AFP server is not running on a Macintosh (and then, probably not using HFS), then this value may not be what the server platform is actually using. And yes, the Finder uses the allocation block size in its calculations to decide how much space is used by a file, so the “size on disk” may not exactly reflect the amount of disk space actually used.
Inside Macintosh Volume VI PBGetVolMountInfoSize typo
Date Written: 1/22/92
Last reviewed: 6/14/93
When I call PBGetVolMountInfoSize to get the size of an AppleShare volume’s mounting information record, the function returns with no errors but ioBuffer points to garbage instead of the size of an AFPVolMountInfo record.
___
The problem you’re having with PBGetVolMountInfoSize is a typo in Inside Macintosh Volume VI on page 25-48. In that call, the ioBuffer field should be a pointer to a word (2-byte) size variable, not a long (4-byte) size variable.
AFP 2.0 FPRead NewLine Mask change
Date Written: 5/3/89
Last reviewed: 11/21/90
I’m confused about the changes to FPRead in AFP (AppleTalk Filing Protocol) version 2.0. How do I use the NewLine Mask?
___
The difference between AFP 1.1 and AFP 2.0 as far as the NewLine Mask is concerned is that, in AFP 1.1, the only legal values of NewLine Mask are $00 and $FF, whereas in AFP 2.0, all values of NewLine Mask are allowed. The NewLine Mask is logically ANDed with a copy of each byte read. If the result matches the NewLine character, the read terminates. The NewLine character is returned as the last byte of data that was read from the fork.
NW 515 - AppleShare Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As in this Technical Note:
Alternate User Authentication Methods (UAMs)
Determining AppleShare Admin password
CreateResFile calls and AppleShare drop folders
Updating aliases when File Sharing state changes
Alternate User Authentication Methods (UAMs)
Date Written: 3/9/93
Last reviewed: 6/24/93
Is there a sanctioned way to use PBVolumeMount to mount a volume with an alternate user authentication method (UAM)? I heard there’s an old document describing AppleShare UAMs.
___
Alternate User Authentication Methods (UAMs) aren’t a supported feature of the AppleShare workstation software. The only documentation to ever come out of Apple concerning alternate UAMs is a draft proposal titled “Multiple User Authentication Methods for AppleShare” and it was written back in 1987. The thing to remember is that the document was a draft proposal; not final documentation for a tested mechanism in shipping product. Apple Developer Technical Support will not supply this document to developers who don’t have it.
Although the code for the alternate UAM mechanism described by that document is in the AppleShare workstation, it has never been fully implemented or tested in any version of AppleShare Workstation (including the AppleShare 3.0 Workstation); it has been only partially tested by some of the engineers that wrote that code. Because the code for alternate UAMs has never been officially tested or documented as a shipping product, Apple Developer Technical Support can’t officially support you in this area. On top of that, engineering doesn’t consider the alternate UAM mechanism part of any current project, so we (in DTS) have no project to submit bugs against. It is very likely that the code for the alternate UAM mechanism in the current AppleShare workstation will be removed at some point, so you should not rely on it in any of your programs.
Since alternate UAMs aren’t a supported feature of AppleShare workstation, new features added to the AppleShare workstation don’t support them, and other parts of the operating system don’t use them. So PBVolumeMount (which is implemented for AppleShare volumes by the AppleShare workstation’s external file system code) doesn’t support alternate UAMs, and the Alias Manager (which uses PBVolumeMount to mount AppleShare volumes) doesn’t know anything about alternate UAMs and has no way to support them.
Determining AppleShare Admin password
Date Written: 2/8/93
Last reviewed: 7/9/93
I mistyped an AppleShare file server’s administrative password. How can I retrieve it?
___
We can’t provide the information you’ve requested since it is considered proprietary (for security reasons). If you’ve lost your admin password you’ll need to delete your current Users & Groups Data File. This is the only sanctioned way to reset your password. (If you have a duplicate Users & Groups file on another server, you can copy this file over and change the password accordingly.)
CreateResFile calls and AppleShare drop folders
Date Written: 4/28/93
Last reviewed: 7/2/93
Why does calling FSpCreateResFile return an afpAccessDenied error (in ResErr) when the destination folder is an AppleShare drop folder?
___
Using any of the CreateResFile calls in a drop box is a useless exercise. Here’s why: The access privileges within a drop box are very limited write-only access. This lets you create new files and then perform a small set of operations on the file while it’s empty (no bytes in either the data or the resource fork of the file). So, while the file is empty, you can open it (either fork) with write-only access (PBHOpenDeny or PBHOpenRFDeny), and write the file’s attributes (PBHSetFInfo or PBSetCatInfo), including Desktop Manager comments. Once either fork has a single byte of data written to it, you can no longer open or change the file’s attributes. This makes it possible to copy a file into a drop folder, but not to manipulate or delete a file (containing data) that’s already in the drop folder. You can also move a file or directory into a drop folder if that file or directory is already on the same server volume.
So, when you call CreateResFile on a drop folder, a new file is created and data is added to the resource fork of the file. Since the file now has data in one of the forks, you cannot open the file or change any of the file’s attributes. FSpCreateResFile fails because after performing the CreateResFile operation that writes data into the resource fork, it attempts to set the file’s attributes (creator, fileType, and scriptTag).
For a quick explanation of drop folder access privileges and rules, see the Macintosh Technical Note “Creating Files Inside an AppleShare Drop Folder” (Files 18). For a complete explanation of what AFP access privileges you need to perform specific operations on an AppleShare (AFP) server, see the section “Directory Access Control” in Inside AppleTalk starting on page 13-31.
Updating aliases when File Sharing state changes
Date Written: 2/4/93
Last reviewed: 7/2/93
We create an alias for a file when File Sharing is off, so the alias doesn’t contain server and zone information. Then we turn on File Sharing and resolve the alias. The file, of course, is found but the alias isn’t marked for an update. Shouldn’t it be updated?
___
According to Inside Macintosh: Files, wasChanged is set to TRUE only on
aliases created by NewAlias (not NewAliasMinimalFromFullPath or NewAliasMinimal) when it sees that key information has changed. The key information is:
• name of the target
• directory ID of the target’s parent
• file ID or directory ID of the target
• name and creation date of the volume on which the target resides
Since none of that changes when you turn File Sharing on or off, the wasChanged flag isn’t set to TRUE. If you’re really worried about it, just call UpdateAlias every time you use the alias (unless you think this would be a major performance hit). Or maybe you should update it only if you notice that it doesn’t have server information and the server is now turned on (to check for this, call PBHGetVolParms and check the bHasPersonalAccessPrivileges bit).
Macintosh AppleShare client version details
Date Written: 12/18/92
Last reviewed: 3/1/93
System 7.0.1 doesn’t seem to correctly display (or display at all) login (greeting) messages from an AppleShare server. System 7.1 works fine. Is this a known problem, and is there anything we can do do get the login messages to show up?
___
Not all Macintosh AppleShare clients support server messages (including the greeting messages). Every version of the Macintosh AppleShare client released since AppleShare 3.0 has supported server messages. If you install the AppleShare client version 3.0, 7.1 or 3.0.1 on System 7.0, 7.0.1 with or without System 7 Tune-up, you’ll get server greeting messages.
Here’s a list of Macintosh AppleShare client versions in the order they were released (notice that they aren’t in version order). We’ve listed the important changes made to each version and listed system software compatibility. (As you might suspect, DTS doesn’t have a complete list of all minor changes made to every version.)
AppleShare Client version: 2.0
Shipped with: System 6.0.x and AppleShare 2.0
System Software versions: 6.0.x
Maximum AFP version: 2.0
Features: Supports AFP 2.0
AppleShare Client version: 7.0
Shipped with: System 7.0
System Software versions: 7.0
Maximum AFP version: 2.1
Features: Supports required AFP 2.1 features only. Adds
support for these new File Manager functions:
PBCreateFileIDRef
PBDeleteFileIDRef
PBResolveFileIDRef
PBExchangeFiles
PBCatSearch
PBGetVolMountInfoSize
PBGetVolMountInfo
PBVolumeMount (no volume password support)
AppleShare Client version: 7.0.1
Shipped with: System 7.0.1
System Software versions: 7.0 or 7.0.1
Maximum AFP version: 2.1
Features: No changes from version 7.0
AppleShare Client version: 3.0
Shipped with: AppleShare 3.0
System Software versions: System 6.0.4 through 6.0.8, System 7.0 and 7.0.1
Maximum AFP version: 2.1
Features: Added support for server greeting messages.
Patched the System 6 File Manager to support
these File Manager functions:
PBGetVolMountInfoSize
PBGetVolMountInfo
PBVolumeMount
PBVolumeMount now supports volume passwords.
AppleShare Client version: 7.1 and 3.0.1
Shipped with: System 7.1 and AppleShare 3.0.1
System Software versions: System 6.0.4 through 6.0.8, System 7.0, 7.0.1,
and 7.1
Maximum AFP version: 2.1
Features: Changes made for international support.
Auto-mounting AppleShare 3.0 volumes when a Greeting is enabled
Date Written: 6/5/92
Last reviewed: 3/1/93
Our program calls PBVolumeMount using MPW 3.2.2 interfaces to auto-mount FileShare and AppleShare servers when performing unattended backups, but if an AppleShare 3.0 server has a Greeting, the backup cannot proceed until the Greeting is dealt with. Is there a way to auto-mount these volumes which suppresses the Greeting?
___
To mount a volume with PBVolumeMount and disable the greetings, you need to set bit 0 in the flags field of the AFPVolMountInfo record. The flags field was marked reserved in Inside Macintosh Volume VI because the greeting message feature had yet to be released when Volume VI was written. The Inside Macintosh: Files book (the revised edition of Inside Macintosh) documents this flag bit.
One thing you should be aware of is an alias record to an AFP volume created by the Alias Manager stores the flags information. That is, if you mount a volume with greetings disabled, create an alias to the volume (or a file or directory on the volume), and then later mount the volume by resolving the alias, the greeting message will be disabled. If the volume is mounted with the flags word cleared, any aliases resolved with show greeting messages (if any).
Here’s a short sample application that mounts a volume with greeting messages disabled:
Program MountVolTest;
USES
Types,
Files;
CONST
kNormalMountFlags = 0;
kInhibitMsgFlags = 1;
TYPE
Str8 = STRING[8];
{ I like the following record structure better than }
{ the AFPVolMountInfo struture in Files.p }
MyAFPVolMountInfo = RECORD
length: Integer; { length of this record }
media: VolumeType; { type of media, always AppleShareMediaType }
flags: Integer; { 0 = normal mount; 1 = no greeting messages }
nbpInterval: SignedByte; { NBP interval ; 7 is a good choice }
nbpCount: SignedByte; { NBP count ; 5 is a good choice }
uamType: Integer; { 1 = 'No User Authent' (guest); }
{ 2 = 'Cleartxt Passwrd'; }
{ 3 = 'Randnum Exchange'; }
{ 6 = '2-Way Randnum exchange' }
zoneNameOffset: Integer; { offset-record start to zoneName }
serverNameOffset: Integer; { offset-record start to serverName }
volNameOffset: Integer; { offset-record start to volName }
userNameOffset: Integer; { offset-record start to userName }
userPasswordOffset: Integer; { offset-record start to userPassWord }
volPasswordOffset: Integer; { offset-record start to volPassWord }
zoneName: Str31; { server's AppleTalk zone name }
serverName: Str31; { server name }
volName: Str27; { volume name }
userName: Str31; { user name (0 length = guest) }
userPassWord: Str8; { user password (0 length = no user password) }
How can I mount a volume without using aliases? I get the mounting information, then attempt to mount the volume. However, the PBVolumeMount call returns an error code.
___
The PBGetVolMountInfo, PBGetVolMountInfoSize, and PBVolumeMount functions are currently handled by only the AppleShare external file system (part of the AppleShare Chooser extension). Those functions are available on AppleShare volumes when the AppleShare Chooser extension is version 7.0 (system software versions 7.0 and 7.0.1), version 3.0 (AppleShare 3.0), or version 7.1 (System 7.1). The AppleShare Chooser extension version 3.0 can be installed on System 6 systems, and then the PBGetVolMountInfo, PBGetVolMountInfoSize, and PBVolumeMount functions can be used in System 6. Other file systems may support these functions in the future. The paramErr error code is returned when these functions aren’t available on a particular volume.
How to tell if someone else has your data file open
Date Written: 7/7/92
Last reviewed: 11/1/92
How can I tell if another person has my data file open? According to Inside Macintosh Volume IV (pages 148–149), PBGetFInfo will tell you if anyone has a file open by returning the first access path found in ioFRefNum, but if I have this file already open, it returns information about myself. I want to be able to tell if anyone else has it open.
____
If the file is on a local volume, you can index through the open FCBs to find all open connections to the file. You’ll find your own connection in that list but since you know what your ioRefNum is, you can ignore that match. For example, the following function will tell you if someone else has the file specified by myRefNum open. With a small change, you could have it return the number of other open connections instead of TRUE or FALSE.
FUNCTION OthersHaveItOpen (myRefNum: Integer): Boolean;
VAR
err: OSErr;
fcbPB: FCBPBRec;
myName: Str255;
myVRefNum: Integer;
myDirID: LongInt;
index: LongInt;
fileName: Str255;
found: Boolean;
BEGIN
fcbPB.ioNamePtr := @myName; { let PBGetFCBInfo fill in the name. }
fcbPB.ioVRefNum := 0; { look on all volumes. }
fcbPB.ioRefNum := myRefNum; { use myRefNum to get info. }
fcbPB.ioFCBIndx := 0; { use ioRefNum instead of ioFCBIndx. }
err := PBGetFCBInfoSync(@fcbPB); { get the open file’s info. }
IF err = noErr THEN
BEGIN
{ save my file’s vRefNum and dirID for matching later. }
{ myName was filled in by PBGetFCBInfo call above. }
myVRefNum := fcbPB.ioFCBVRefNum;
myDirID := fcbPB.ioFCBParID;
{ index through the open files on the volume }
index := 1;
REPEAT
fcbPB.ioNamePtr := @fileName;
fcbPB.ioVRefNum := myVRefNum;
fcbPB.ioRefNum := 0;
fcbPB.ioFCBIndx := index;
err := PBGetFCBInfoSync(@fcbPB);
IF err = noErr THEN
{ see if there is a match that isn’t myRefNum }
found := (fileName = myName) AND
(fcbPB.ioFCBParID = myDirID) AND
(fcbPB.ioRefNum <> myRefNum)
ELSE
found := FALSE; { no matches on errors }
index := index + 1; { next index position... }
UNTIL found OR (err <> noErr);
OthersHaveItOpen := found;
END
ELSE
OthersHaveItOpen := FALSE; { we don’t even have it open! }
END;
On nonlocal volumes (AppleShare volumes), you can use PBHOpenDeny with the deny-read and deny-write permissions to ensure nobody else can open a file you have open. You can tell which volumes are nonlocal by calling PBHGetVolParms and looking at the value returned in the GetVolParmsInfo.vMServerAdr field. If that value is 0, the volume is local.
Unmounting volumes shared with Macintosh File Sharing
Date Written: 9/15/92
Last reviewed: 3/10/93
I tried to unmount a volume shared with Macintosh File Sharing from my program using the following steps: I shut down the file service with the SCShutDown server control call; I call SCPollServer to make sure the file service is really off (scServerState = SCPSJustDisabled); then, I call PBUnmountVol to attempt to unmount the volume. It didn’t work because PBUnmountVol fails with fBsyErr (-47). I broke on the _UnmountVol trap because the AppleShare PDS file, where the file server keeps the access privilege and share-point information for the shared volume, was open. Why is AppleShare PDS still open when I’ve turned the file service off? How can I close it and unmount the volume?
___
SCPollServer returns the state of the file service, not the file server application (in this case, File Sharing Extension is the file server application). When SCPollServer returns a server state of SCPSJustDisabled, the file service is off; however, the file server application may or may not still be running. The AppleShare PDS file will eventually get closed before the file server application quits.
There’s an easy way to determine when the File Sharing application has quit (and thus when the AppleShare PDS file is closed): just use the Process Manager GetNextProcess and GetProcessInformation calls to find out when File Sharing Extension is no longer running. The File Sharing Extension application has a processType of 'INIT' and a processSignature of 'hhgg'. Here’s a function you can use to see if the File Sharing Extension application is running:
myPInfoRec.processName := NIL; {Don't need process name}
myPInfoRec.processAppSpec := NIL; {Don't need process location}
FileSharingAppIsRunning := FALSE; {Haven't found it yet}
WHILE (GetNextProcess(myPSN) = noErr) DO
IF GetProcessInformation(myPSN, myPInfoRec) = noErr THEN
IF (myPInfoRec.processSignature = FileSharingSignature)
THEN
FileSharingAppIsRunning := TRUE; {Found it}
END;
After shutting down the file service, your event loop will need to poll with FileSharingAppIsRunning because you must give the file server application processing time to close files, dispose of memory, and perform other shutdown operations. If you poll with FileSharingAppIsRunning without giving other processes time, File Sharing will never shut down.
Maximum volumes for file sharing
Date Written: 3/9/92
Last reviewed: 8/1/92
In the past I’ve been able to file share more volumes off my Macintosh SCSI storage devices than I can with System 7. Now I get an alert saying: “One or more items could not be shared because not all volumes are available for file sharing.” Please advise as to what the problem might be.
___
Macintosh File Sharing will only prepare for sharing the first 10 volumes it sees (it enumerates the volume list with PBHGetVInfo). The volumes you can’t share will usually be the ones mounted last. The reason you used to be able to share another set of volumes probably has to do with some change you’ve made (like changing the boot volume or a volume’s SCSI ID number).
So, you’ve just hit the limits of File Sharing. The solution to your problem is to use AppleShare 3.0—it will share up to 50 volumes. File Sharing wasn’t intended to be the end-all in file servers; it was designed for individuals who want to occasionally share files with a small number of other users. Here are some limits to File Sharing that you should note:
• The number of users and groups in the Users & Groups Data File is limited to 100 total. (The limit with AppleShare 3.0 is 8192 total.)
• The number of users that can be logged in at one time is 10 (this doesn’t count the owner of the system, one remote connection is always reserved for the owner of the system). (The limit with AppleShare 3.0 is 120.)
• The number of share points available for regular users is 10. (The limit with AppleShare 3.0 is 50.)
• The number of sharable volumes (what the owner sees when he or she logs in remotely and what can be shared or partially shared) is 10. (The limit with AppleShare 3.0 is 50.)
AppleShare 3.0 also supports many other user (for example, server messages), security, and developer features (server control calls and the server event mechanism) not supported by Macintosh File Sharing.
AppleShare user limit
Date Written: 11/16/90
Last reviewed: 12/19/90
What is the maximum number of users that can be logged in to any one AppleShare file server? What can we do to increase the limit? Will upgrading to AppleTalk Phase II help? Is there an upgrade to the AppleShare 2.0.1 software?
___
AppleShare currently has a limit of 50 simultaneous users. This is a limitation in the software and is not related to AppleTalk. Changing from AppleTalk Phase I to Phase II will not change anything. The next version of AppleShare might raise this limitation. We do not have any projected dates for a release of the next version of AppleShare. You may want to periodically check with APDA for any update or new release.
Maximum number of users supported by AppleShare for each CPU
Date Written: 5/3/89
Last reviewed: 11/21/90
What is the maximum number of users supported by AppleShare? Does this number change based on the type of CPU being used for the server?
___
The following chart lists some current AppleShare limits (AppleShare 1.1, 2.0, and 2.01) which are based upon the chosen server platform and memory configuration. The limits that otherwise might be present on a workstation are still in effect, and are not affected by the workstation being logged in to an AppleShare server. These limits will change in the future.
Server machine is Macintosh Plus, SE, or II with 1 MB:
Number of users: 25
Number of locked ranges: 1000
Number of open files: 80
Number of volumes: 16
Server machine is Macintosh II with more than 1 MB:
Number of users: 50
Number of locked ranges: 2000
Number of open files: 160
Number of volumes: 16
X-Ref:
Macintosh Technical Note “AppleShare 1.1 and 2.0 Limits”
Macintosh file system active ranges
Date Written: 3/18/91
Last reviewed: 6/7/91
How many active ranges can a Macintosh application have on a shared file? If the answer is more than one, is the limit per application or per machine? If two ranges overlap, are they joined into one range? Can an application nest ranges? For example, if an application’s user performs an action that forces a record to be locked and later the application locks the full range of the file, does the initial record lock disappear?
___
The only way to determine the limit is to hit the limit and get a NoMoreLocks error. The number of range locks supported is a limit of the server platform, and that limit is shared by all users of the server (at least it is with Apple’s AppleShare server software). With Apple’s server-based version of AppleShare, approximately 40 locks per user are allowed (for example, if the server allows 25 users, there are 1000 locked ranges total; if the server allows 50 users, there are 2000 locked ranges total; and with File Sharing running under System 7.0, approximately 20 locks are allowed per user). Other vendors may allow more or fewer locked ranges on their implementations of an AppleTalk Filing Protocol (AFP) server. Notice that the numbers given are per user, not per application. It’s assumed that a user probably won’t need more than a few locks at a time on a single file.
You cannot have range locks that overlap. You’ll get a RangeOverlap error from AFP. All the rules for range locking can be found in the AFP chapter of Inside AppleTalk (page 13-56). Additional information on AppleShare limits is available on the latest Developer CD Series disc.
The Macintosh Technical Note “Lock, Unlock the Range” covers several important details about PBLockRange and PBUnlockRange that are not in Inside Macintosh.
AppleShare open file limit
Date Written: 10/8/91
Last reviewed: 10/8/91
On an AppleShare 2.0 File Server platform, the only application that can access files outside of the Server Folder (that is, the System Folder) is the file server application. AppleShare Foreground applications (described in the Macintosh Tech Note “AppleShare Foreground Applications” are the only other applications that should be running on a server and they can only access files inside the Server Folder. All file forks (referred to as files from here on) opened by remote AppleShare workstations are opened by the File Server application.
The File Server application will open a file only one time. All access to that file from any number of workstations will use the single access path the File Server has opened. Only when all workstations have closed the file does the File Server really close the file on the server. So, that means only one FCB is used on the server per open file, even if 50 users have shared access to that file.
The File Server application handles all access control to an open file using the AppleTalk Filing Protocol (AFP) deny-mode permission model. The only reason a user won’t be able to open an access path to a file on a server is if another user has opened that file with a deny-mode that conflicts with the second user’s request, or the user does not have the access rights needed to open files in the file’s parent directory or directory ancestors. The AFP deny-mode permission model is described briefly in Inside Macintosh Volume V, File Manager Extensions in a Shared Environment, and in detail in the AppleTalk Filing Protocol chapter of Inside AppleTalk.
As noted in the Macintosh Tech Note “AppleShare 1.1 and 2.0 Limits,” the maximum number of open file forks on an AppleShare 2.0 server is either 80 on a 1 MB MC68000 server platform, or 160 on a server platform with more than 1 MB and a MC68020 or greater processor. That figure includes the number of files kept open by the system and the file server application. If an AppleShare Foreground application is running on the server (for example, the AppleShare Print Server), then any files it may have open count against the maximum, too. The same can be said for open desk accessories. This Tech Note currently doesn’t say anything about those files counting towards the limit. If the 160 (or 80) file limit is a problem, you can use the “Up Your FCBs” INIT to bump the number available up to the maximum (342) allowed by the File Manager. “Up Your FCBs” can be found on AppleLink in the Developer Support: Developer Technical Support: Hacks folder.
Software-selecting an AppleShare volume
Date Written: 10/23/90
Last reviewed: 2/20/91
Is there any source code available for mounting/unmounting AppleShare volumes?
___
There are actually a couple of ways to select an AppleShare volume. You could use the Choose tool in MPW that accomplishes this, or you can do it with aliases under System 7. Other than the MPW tool, there is no other supported way of doing this under pre-7.0 systems; there are no current hooks to allow easy mounting of AppleShare volumes programmatically. It gets pretty nasty trying to figure out everything that is necessary to accomplish this, which is why people here pretty much stay away from this as well. Also, some low-level stuff may be proprietary, which is why the tool is supplied for developers. The Choose tool is described in the MPW docs. It should be pretty straightforward to use.
2.0.1 PBHGetDirAccess and PutDirAccess restrictions
Date Written: 12/5/90
Last reviewed: 1/16/91
If a volume is connected to an AppleShare server, but is not an AppleShare volume, will the PBHGetDirAccess (and PutDirAccess) function work on it? Can an INIT on the server make these calls?
___
For AppleShare 2.0.1, the INIT cannot make these calls on non-file server volumes. In future versions, the PBHGetDirAccess and PutDirAccess calls can safely be made on all volumes connected.
Server Move & Rename folder
Date Written: 12/5/90
Last reviewed: 6/14/93
A folder is created in the Server Folder called “…Move & Rename.” What is this and what are its contents? Should it be backed up? Are there any other temporary folders and files that might need to be backed up?
___
It’s the “$01$02$03Move & Rename” folder that AppleShare 2.0.1 and future versions create for the two-step process of moving and renaming a file or a folder, a feature that is not provided via HFS. It should be backed up, but in general will not contain anything. (It has something in it only for a brief instant and only if the server has IBM PCs or some other computer that uses this call. Macintosh systems don’t.) It needs to be backed up for 2.0.1 so that the folder is there if the server is restored. (Otherwise, Admin will have to be run to create a new one, a somewhat disconcerting action to perform after completely restoring a file server.)
How to tell if application’s running on a server
Date Written: 12/5/90
Last reviewed: 1/16/91
What is the best way to determine if a Macintosh application is running on a server?
___
For 2.0.1 you can test the longword at $B50. If it is 0 or -1, the server is not running. If it isn’t—that is, it’s a real address—then the server is either starting up, or is running. There might be a hook available in future versions of AppleShare that your process can hook into.
Detecting AppleTalk being closed down by user
Date Written: 12/12/90
Last reviewed: 6/14/93
How do I detect that a user has closed down my AppleTalk connection (by turning AppleTalk off from the Chooser or by changing network connections from the Network control panel)?
___
The AppleTalk Transition Queue provides a means to determine when the AppleTalk drivers change status or when they might be closed in the very near future. The Transition Queue informs its clients (everyone who has asked to be added to the queue) each time the state of the .MPP driver changes state (opened or closed) or is about to change state.
The AppleTalk Transition Queue is documented in Inside Macintosh Volume VI, Chapter 32 (The AppleTalk Manager) and is also documented in the Macintosh AppleTalk Connections Programmer’s Guide, Chapter 3 (Calls to the LAP Manager), available from APDA. A sample AppleTalk Transition Queue routine is shown in Tech Note 311.
Purpose of AppleShare SP file
Date Written: 3/14/91
Last reviewed: 4/29/91
What is the file “AppleShare SP” and what does it do? The AppleShare File Server seems to run without it, and it reduces the alert sound to just a beep even when the server is not running on that computer. Is the file really needed?
___
You do need the AppleShare SP INIT on your file server. The AppleShare SP (Small Patch) INIT is designed to correct a minor incompatibility between AppleShare 2.0x and the Sound Manager. The INIT forces the Macintosh to use the “Simple Beep” sound at all times. System 7.0 file sharing and future versions of AppleShare do not need the INIT.
Macintosh EOF in an AppleShare environment
Date Written: 3/18/91
Last reviewed: 6/10/91
I ran into the following when updating the logical end of file (EOF) of a shared file: Application A and Application B have access to a file under AppleShare. Each is using fsRdWrShPerm. When Application A changes the logical EOF, Application B doesn’t seem to notice that EOF has changed until Application B calls GetEOF. Is there a better way to make Application B aware of the change of logical EOF?
___
You’ve made a correct assumption that the correct way to keep track of EOF in an AppleShare environment is to ask for it. When you open a file, the AppleShare workstation code translates the Macintosh operating system Open call to the AFP (AppleTalk Filing Protocol) FPOpenFork call, and sets the bits in the bitmap parameter to current length of the fork opened (in the case of Open, the data fork). It then uses THAT as the EOF for future operations unless it gets an update from the server. Because the server does not constantly update everyone who has the file open, you have to ask to find if another user (or application) has made a change. Just remember that using GetEOF will only get you the EOF at that instant in time. Someone else sharing the file could change EOF right after you check it.
The PBLockRange function can be used by an AppleShare aware application to prevent another user from appending data to a shared file while you are appending data. For example:
paramBlock.ioRefNum := myFileRef;
err := PBGetEOF(@paramBlock, FALSE); {get the current EOF}
{check for errors in a real application}
oldEOF := paramBlock.ioMisc; {save the current EOF}
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := oldEOF; {start range lock at current EOF}
err := PCLockRange(@paramBlock, FALSE); {and lock the rest of the fork}
{check for errors in a real application}
{now you can append data to the file}
paramBlock.ioRefNum := myFileRef;
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := oldEOF;
err := PCUnlockRange(@paramBlock, FALSE); {unlock the locked range}
{check for errors in a real application}
PBLockRange can also be used when you need to truncate a shared file. Locking the portion of the file you’re about to truncate prevents another user from using that portion during the truncation process. For example:
paramBlock.ioRefNum := myFileRef;
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := theNewEOF; {start lock at truncation point}
err := PCLockRange(@paramBlock, FALSE); {and lock the rest of the fork}
{check for errors in a real application}
paramBlock.ioMisc:= theNewEOF;
err := PBSetEOF(@paramBlock, FALSE); {set the new EOF (truncate the file)}
{check for errors in a real application}
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := theNewEOF;
err := PCUnlockRange(@paramBlock, FALSE); {unlock the locked range}
{check for errors in a real application}
The entire fork can be locked with:
paramBlock.ioRefNum := myFileRef;
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := 0; {lock from the beginning}
err := PCLockRange(@paramBlock, FALSE); {lock the whole fork}
{check for errors in a real application}
{do your thing}
paramBlock.ioRefNum := myFileRef;
paramBlock.ioReqCount := -1; {$FFFFFFFF}
paramBlock.ioPosMode := fsFromStart;
paramBlock.ioPosOffset := 0; {unlock from the beginning}
err := PCUnlockRange(@paramBlock, FALSE); {unlock the whole fork}
{check for errors in a real application}
Macintosh AppleShare versus file sharing capabilities
Date Written: 4/3/91
Last reviewed: 6/21/91
We are using the file sharing capabilities of Macintosh systems with System 7.0 to make them mini file servers. Where can information that details the features of both AppleShare and file sharing be found? We are considering using only file sharing in the office if it is capable of providing most of what AppleShare provides.
___
Information on file sharing can be found in the System 7 Personal Upgrade Kit and in Inside Macintosh Volume VI, on your Developer CD Series disc. The maximum number of concurrent connections allowed on a Macintosh using file sharing is 10. The performance of an AppleShare file server (the standard kind of server) is approximately 25 percent better than a similar configuration of Macintosh computers acting as a file sharing server.
System 7 and AppleTalk Internet Router
Date Written: 9/17/91
Last reviewed: 11/25/91
We’ve tried to run the Apple Internet Router with our System 7 file sharing servers. There does not appear to be support for multiple networks. Is there some solution to this?
___
The AppleTalk Internet Router and System 7 are compatible, with two exceptions: virtual memory and 32-bit addressing. You need to drag-install it instead of using the Installer. The Installer script on the router disk will put the parts of the router in the wrong place. Here are the steps to drag-install the router:
1. Drag the files Router, LocalTalk (Built-in), and LocalTalk (Modem) from the System Folder on the AppleTalk Internet Router disk to the closed System Folder on the disk where you want to install. System 7 will automatically put the Router file in the System Folder, and put the LocalTalk (Built-in) and LocalTalk (Modem) files in the Extensions folder in the System Folder.
2. Under System 7, open the System file on the AppleTalk Internet Router disk (double-click the System file). A window will open showing the desk accessories, fonts, and sounds that are part of that System file. Drag the Router desk accessory from that window to the closed System Folder on the disk where you want to install. System 7 will automatically put the Router desk accessory in the Apple Menu Items folder in the System folder.
3. Reboot.
That’s all there is to it.
X-Ref:
“System 7: Installing Internet Router 2.0,” AppleLink Tech Info Library
TMGetTermEnvirons envVersTooBig error
Date Written: 9/17/91
Last reviewed: 9/17/91
A call made to TMGetTermEnvirons returns -5502 or envVersTooBig. The call is made with a good terminal handle started from your TTY tool. What’s wrong? How do I fix it?
___
When you call TMGetTermEnvirons, the TermEnvironRec that you hand it a pointer to must have initialized the version field with curTermEnvRecVers. The following will work properly:
void getTEnvirons(TermHandle aTerm)
{ ...
TermEnvironRec tEnv;
TMErr err;
...
tEnv.version = curTermEnvRecVers;
err = TMGetTermEnvirons(aTerm,&tEnv);
/* check for errors, do whatever... */
...
}
This is consistent with most other Macintosh “get environment” calls such as SysEnvirons, and is documented (somewhat unclearly) at the top of page 113 in Inside the Macintosh Communications Toolbox.
Modifying a server volume’s backup date-time from a workstation
Date Written: 12/5/91
Last reviewed: 1/27/92
How can I change the backup date of a remote AppleShare volume? When I get the volume information with PBHGetVInfo (followed by a PBFlushVol), change the backup date field, and call PBSetVInfo, the date is changed in my local copy of the volume information, but when I unmount and remount the AppleShare volume, the original backup date is still there.
___
On an AppleTalk Filing Protocol (AFP) file server, two of the volume date-time values, the volume creation date-time and the volume modification date-time, are managed solely by the server and can’t be changed by workstations. The third volume date-time value, the volume backup date-time, can be set by a workstation with only one AFP call, afpSetVolParms. However, the File Manager, through the Macintosh AppleShare external file system, does not give an application a way to make the afpSetVolParms call. That leaves only one way you can change a server volume’s backup date-time from a workstation: You’ll have to use the AppleTalk .XPP driver to access the server directly.
Using the .XPP driver to change the backup date-time involves these steps:
• Open the .XPP driver and get the driver reference number.
• Use the afpLogin variant of AFPCommand to start a session and log in to the server. If the “Randnum Exchange” or “2-Way Randnum Exchange” user authentication methods are used, you will receive an AuthContinue error (-5001) from the afpLogin call and you’ll have to follow up the afpLogin call with an afpLoginCont call (through AFPCommand again) to finish the log-in sequence.
• Once you’re logged in to the server, you need make an afpGetSrvrParms call to get a list of volumes and to find out if the volume you’re interested in has a password associated with it.
• Then you need to call afpOpenVol with the volume name (and password if there is one). You can have afpOpenVol give you the volume’s current backup date-time and other volume information if you set the appropriate bits in the bitmap parameter passed to afpOpenVol.
• Now that you’re logged in to the server and have the volume opened, you can make an afpSetVolParms call to change the backup date-time.
• After changing backup date-time, you need to close the volume with afpCloseVol, and then log off the server with afpLogout.
The .XPP driver’s AFP commands are described in Inside Macintosh Volume V in the AppleTalk chapter (pages V-524 through V-550). For a description of the AFP calls, user authentication methods, and other AFP information, you need to look in the AppleTalk Filing Protocol chapter of Inside AppleTalk. If you decide you want to really use the .XPP driver as described above and want to use the 2-Way Randnum Exchange user authentication method supported by System 7 File Sharing and AppleShare 3.0, contact DTS for a preliminary version of the AFP 2.1 specification that describes that new authentication method.
AppleShare Print Server 3.0 and AppleTalk self-send
Date Written: 2/28/92
Last reviewed: 2/28/92
When I issue a PAPWrite from my application to the AppleShare Print Server 3.0 running on the same Macintosh, PAPWrite locks up in a tight loop. If I send to a LaserWriter or the AppleShare Print Server 3.0 running on a different Macintosh system, all works well. The LaserWriter Font Utility 7.0 behaves the same as my application: It works if the spooler is remote and locks up if the spooler is local.
___
You’re probably calling PAPWrite and then not giving up any system time needed by the print server to process the data you sent to it. That just doesn’t work in the self-send environment. For example, the following won’t work:
What your application should do is drop back into its event loop after making the PAPWrite call and then poll compState to see when the PAPWrite completes. By calling WaitNextEvent from your event loop, your application gives the print server application the time it needs to receive and process the data you sent to it.
The LaserWriter Font Utility wasn’t designed to work with print servers and will exhibit the same problem your application is experiencing.
System 6 & 7 Chooser AppleShare differences
Date Written: 2/28/92
Last reviewed: 2/1/93
What’s the limit on the number of servers displayable in the Chooser as well as the maximum number of AppleShare mount points per server? Are the System 7 limits the same as for System 6?
___
Most System 6 Chooser limitations have been eliminated with the System 7 Chooser. Here’s how each version operates:
System 6 Chooser:
The 6.0 Chooser’s LookupName call to find AppleTalk entities is made asynchronously where retBuffPtr points to a 512-byte buffer and maxToGet = 32 (this is the 32-device limit per device type you may have heard of). The important thing to note here is the return buffer size (512 bytes). For example, if you are looking for AppleShare servers in your own zone (the “*” zone), the number of overhead bytes per NBP tuple returned will be 16 (5 for the entity address, 10 for the string “AFPServer”, and 2 for the string “*”). If there were 20 servers in your zone, 340 bytes of the 512-byte buffer are used before you start counting the space used by the server names. That leaves 172 bytes for the names or around 8 characters per name (1 length byte plus 8 characters). If the average server name is longer than that, there won’t be enough room to collect all of the NBP replies and one or more servers won’t show up in the list.
Once a server is selected and the user is authenticated, the AppleShare 2.0 RDEV uses afpGetSrvrParms to ask for the list of server volumes. The AppleShare 2.0 RDEV uses a 512-byte buffer for the replies. After the overhead used by the AppleTalk protocol headers, that’s enough room for around 16 volumes with full-sized names; more if the names aren’t full-sized.
System 7 Chooser:
The System 7.0 Chooser fixes the problem with the NBP buffer completely. It dynamically sizes the NBP LookupName return buffer. So, if numGotten => maxToGet, it will make the return buffer larger and increase the value of maxToGet. The System 7.0 Chooser starts with retBuffSize=1024 and maxToGet=256.
The AppleShare 7.0 and 3.0 RDEVs increased the size of the afpGetSrvrParms reply buffer to 1728 bytes. That’s still not big enough to get 255 volumes (the AFP limit) with full-sized names. However, it is big enough for 50 volumes with full-sized names, the maximum number of volumes supported by AppleShare 3.0.
For both System 6 and 7 Choosers, the only limits imposed on the zone are the List Manager limits of 32K of data per list. If each zone name were 33 characters, for example, that would give you space for roughly 1000 zones.
Server and workstation clock times
Date Written: 2/25/92
Last reviewed: 4/22/92
If I hook up two Macintosh computers over LocalTalk, turn on Personal File Share, mount one computer’s volume on the other, and make changes to files on each machine, the Get Info mod dates are not adjusted. In my case, machine A’s clock said 10:20 and machine B’s said 10:30. From machine B, I made a change to a file on machine A. Then, still on machine B, I did a Get Info on that machine A file. Its mod date said 10:20. I then instantly made a change to a file (from machine B still) on machine B and did a Get Info on it and its mod date was 10:30. In other words, the mod dates were not adjusted and reflected the time of the machine each file was located on. Am I misinterpreting something?
___
The way the workstation computes the server time is not quite as straightforward as is documented in Inside AppleTalk, 2nd edition, page 13-21. When a workstation logs onto a server (File Share or AppleShare), the difference between the workstation’s clock and the server’s clock (s – w) is computed. All subsequent server date/time values as seen by the workstation are computed by adding this difference (s – w) to the server data/time (workstation time = server time + (s – w)).
However, it looks as if the Macintosh workstation also uses the following algorithm to compute the adjusted server time:
• if the offset (s – w) is 15 minutes or less, report the server time as is
• if the offset (s – w) is greater than 15 minutes, compute the offset rounded up to the nearest 30 minute interval.
For example, let’s say you have two machines, A and B. B logs on to A. B then goes and modifies a file on A. Listed below are the clock times that the modification took place, and in the rightmost column is the mod. time that B would see for the modified file on A.
A time B time mod. time as seen by B
------ ------ ----------------------
11:09 11:22 11:09
11:04 11:20 11:34
4:34 7:14 7:05
11:22 11:53 11:52
In the first example, the difference (s – w) is (11:22 – 11:09) = 13 minutes. Since 13 is less than 15 minutes, B sees the server time as is. In the second example, (s – w) is (11:20 – 11:04) = 16 minutes which is greater than 15 minutes so compute the offset to the nearest 30 minute interval (30 – 16) = 14, and 11:20 + 14 = 11:34. In the third example, (s – w) is (7:14 – 4:34) = 2:40 which is greater than 15 minutes so compute the offset to the nearest 30 minute interval (30-40) = –10, and 7:14 – 10 = 7:05. In the last example, (s – w) is (11:53 – 11:22) = 31 minutes so compute the offset to the nearest 30 minute interval 30 – 31 = –1, and 11:53 – 1 = 11:52.
You are probably asking why the 15-minute cushion and why round to the nearest 30-minute interval? Possibly it’s an attempt to approximate a modification time somewhere in between the workstation and server times.
PBCatSearch on AppleShare volumes
Date Written: 3/11/92
Last reviewed: 5/21/92
PBCatSearch acts differently on a local hard disk than on an AppleShare volume. Say, after a couple of successful PBCatSearch operations on a volume, the user modifies the directory by duplicating, renaming, or removing a file. An error is returned, and (theoretically), the search can continue. If you do this on a local hard disk, everything is cool. After making the change, the next PBCatSearch call returns -1304 (catChangedErr), but subsequent calls return noErr and continue to find files. However, if you run this on an AppleShare 3.0 volume, the first call after the change returns -5037 (afpCatalogChanged), but all following calls continue to return that error, and “find” the same file that was found on the last good attempt. So what gives?
___
The afpCatSearch AFP call does not map exactly to the File Manager’s PBCatSearch call. This isn’t uncommon in File Manager to AFP translations because AFP calls are designed to be more general so they can be implemented on platforms other than the Macintosh. In some cases, AFP keeps more information than the Macintosh requires (for example, ProDOS file type mapping information for Apple II systems and short names for DOS workstations) and in other cases Macintosh-specific information is “generated” by the Macintosh workstation software (for example, allocation block sizes in the Volume Control Block). Here are specific differences I’ve found between PBCatSearch and afpCatSearch:
• afpCatSearch and the AppleShare workstation implementation of PBCatSearch do not use ioSearchTime. The AppleShare 3.0 server searches for up to 1 second or 4 matches maximum and then returns to the workstation with whatever matches (0-4) are found within areas of the disk that user has access to. The AppleShare workstation keeps asking for the number of matches requested minus the total matches returned until it gets the number requested, or the server returns an error.
• AFP 2.1 does not support both physical and logical fork lengths. If a PBCatSearch call uses fork lengths, the upper bound (in the afpCatSearch Spec2 field which comes from the ioSearchInfo2 record) becomes the maximum of the logical and physical lengths and the lower bound (in the afpCatSearch Spec1 field, which comes from the ioSearchInfo1 record) becomes the minimum of the logical and physical lengths.
• AFP 2.1 does not support the fsSBNegate ioSearchBits bit. If a PBCatSearch call uses fsSBNegate, that bit will be ignored by the AppleShare workstation and server and you’ll get back exactly the opposite of what you expected. This is an unfortunate omission from AFP 2.1. Because it is implemented this way in at least two shipping servers, the fsSBNegate cannot be added without a revision to the AFP specification.
• The File Manager PBCatSearch call doesn’t return any matches when a catChangedErr occurs. However, it does return an updated ioCatPosition record which can be used to make another PBCatSearch call (this may result in your search either missing a few entries or getting a few duplicate matches). afpCatSearch does not work that way. afpCatSearch only returns AFP reply data (which includes the ioCatPosition record) if the FPError is noErr or afpEofError. The current ioCatPosition record is not returned to the workstation if any other error occurs. So, if an afpCatalogChanged error occurs, the ioCatPosition record is not returned to the workstation and the workstation returns ioCatPosition to the caller of PBCatSearch unchanged. Since the ioCatPosition record is still invalid, calling PBCatSearch again with the same invalid ioCatPosition record will just return the afpCatalogChanged error again. The conclusion from this explanation is that you can continue a search if PBCatSearch returns a result of noErr or catChangedErr. The search completed if PBCatSearch returns a result of eofErr. All other results from PBCatSearch (including afpCatalogChanged) indicate that you must restart the search from the beginning by clearing the initialize field of the ioCatPosition record.
AppleShare Prep file and boot-mounting volumes
Date Written: 8/25/92
Last reviewed: 9/15/92
I have selected AppleShare volumes to mount at system startup by checking the volumes in the Chooser list. If I’m on a nonextended network and I call an extended network via AppleTalk Remote Access and log into a remote server via the Chooser and AppleShare, an error alert will say “The AppleShare Prep file needed some minor repairs. Some AppleShare startup information may be lost” and all the information about my local nonextended network will be cleared out of the AppleShare Prep file, so I loose all my log-in IDs and passwords for my local servers. The same thing happens going back the other way (extended to nonextended). Why is this happening?
___
There are several problems you can run into when you connect two networks (and that’s what you’re doing when you use AppleTalk Remote Access when you’re already connected to a network). The problems are usually the result of duplicate names or duplicate node numbers.
The “boot mount list” (BML) kept in the AppleShare Prep file stores the location of volumes that you want mounted at boot time. Part of that location is the zone name. If you create entries to the BML when you aren’t on an extended network (that is, when you have no zones), the zone name stored in the BML is “*” (“*” is AppleTalk’s shorthand for “this zone”). If you create entries to the BML when you are on an extended network (that is, when you have zones), then the zone name stored in the BML is the zone name of the server.
The boot mount code checks the validity of the BML when the system starts up, and the Choose checks the validity of the BML when it’s opened. If there are no zones, then entries with zone names other than “*” are cleared out and an alert saying “The AppleShare Prep file needed some minor repairs. Some AppleShare startup information may be lost” is displayed because those entries aren’t valid. If there are zones, then entries with zone names of “*” are cleared out and the alert is displayed because the “*” zone name isn’t a reliable way to save the zone location of a server on an extended network. The “*” zone isn’t reliable for storing the zone name because a workstation can easily be moved from zone to zone, keeping the same NBP object and NBP type names. This is especially true with AppleTalk phase 2, which supports multiple zones on a single network (for example, multiple zones on the same piece of Ethernet cable).
The workaround for boot-mounting volumes is to create alias files to the file servers you want to mount at boot time and then drop those alias files into the Startup folder inside your System Folder. The only drawback to this is aliases don’t save the user’s password. If you need boot-mounted volumes without the password dialog, you’ll have to use guest access.
NW 520 - AppleTalk Overview Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As this month:
Documentation for creating an AppleTalk-aware network device
Documentation for creating an AppleTalk-aware network device
Date Written: 1/12/93
Last reviewed: 6/14/93
Where can I find information for creating an AppleTalk-aware network device?
___
The Inside AppleTalk reference provides much of the protocol information required for your device to communicate with networked Macintosh systems. Inside AppleTalk is available from APDA (#C0078LL/B).
For writing hardware device drivers, the Macintosh AppleTalk Connections Programmer’s Guide discusses information on writing ADEVs and 'atlk' and driver resources. This guide helps one to understand the workings of the Link Access Protocol Manager, and how packets are handled to make sure they go out through the right port.
Apple doesn’t provide information about the hardware design of an AppleTalk-aware device. In addition, information concerning the hardware layer of LocalTalk hasn’t been made available other than that provided in Inside AppleTalk. The best source of information on this subject probably is from the Internet or some other N&C development community. For Ethernet compatible devices, some of the information that you’ll need can be obtained from the developer notes available from the vendors of Ethernet chips, such as National Semiconductor, Inc., manufacturer of the SONIC chip.
Another useful tool for developing such a product is a network sniffer, so that you can watch the packet exchange between devices, and compare the exchange with a similar AppleTalk device. This will help in determining whether your device has correctly implemented the protocol. You can probably find product information regarding the various sniffers available by looking on the Redgate icon on AppleLink or in your favorite product catalog.
Broadcasting to all internet nodes
Date Written: 9/22/92
Last reviewed: 6/14/93
I want to send a Broadcast to all the nodes on an internet, whether EtherTalk or LocalTalk, when my application comes up. I’m not sure which AppleTalk protocol to use. I tried using ALAP and DDP but couldn’t get either to work.
___
Unfortunately, you can’t broadcast to an entire AppleTalk internet. In order to limit network overload, broadcast packets are localized. On AppleTalk, they don’t extend over zones and, on Ethernet, they don’t cross bridges. What you might do, however, is something roughly like the following:
Server side:
1. Initialize your application by creating a socket in the “server” address range:
ioParam.ioNamePtr = "\p.MPP";
ioParam.ioMisc = (Ptr) 0x80000000; /* Server flag */
PBOpenSync(&ioParam);
2. Create an ATP socket:
POpenATPSkt(&atpParam, 0); /* Synchronous */
gMySocket = atpParam.ATP.atpSocket;
3. Register your name. The NBP objStr should be the name of the system your application is running on. You can use GetString(-16413) to get the system name on System 7 (or -16096 to get the Chooser name). The NBP typeString should be a name unique to your application. Note: be sure to remove the name before your application terminates. If you get error -1027 (nbpDuplicate), a previous instance of your application terminated without removing the name. Just call PRemoveName and try again.
4. Your server should now post an ATPRead and wait for messages.
Client side:
The “client” is the part of your application that looks for servers. The algorithm is, roughly, as follows:
1. Use GetZoneList to get a complete list of AppleTalk zones. Make sure you handle the “no zones” case correctly.
2. For each zone, use PLookupName to get a list of servers with the NPB typeStr that the “server side” registered.
3. For each found entity, use NBPExtract to get the entity name and the addrBlock. The entity name gives you the “human readable” text that identifies the network zone and system name, while the addrBlock lets you send ATP messages to the other system.
The AppleTalk program interface is described in Inside Macintosh Volumes V and VI. Use these as your primary reference, referring to Inside Macintosh Volume II only when necessary.
Note that you have to figure on at least 15 seconds per zone. This means that, if you’re trying this algorithm on some huge network (like the Apple engineering network), your application will probably need over a half-hour to probe every zone. The reason for mentioning this is that some applications are using network-uniqueness as a form of user license enforcement. If you do this, it would be unfair to the honest user to stall the application for a half-hour to check for duplicates.
Another application use would be for systems that maintain a central server, such as for a database, that handles many clients. Here, you probably should ask the user for the zone:node of the server, remember this in your application’s preference file, and look for that server.
One other thing: In writing this type of program, the SetSelfSend capability is extremely helpful: that way, you can debug both server and client functions on one machine — indeed in one application. Even if you don’t normally use SetSelfSend, make sure your application handles it as it is a global state for all AppleTalk connections on the machine.
How to get the User and Computer names used by AppleTalk
Date Written: 11/27/91
Last reviewed: 6/14/93
I’d like to use the same names that the system uses to identify itself on the AppleTalk network in my program. Where can I find those names?
___
The names used by the system for network services are stored in two 'STR ' resources in the System file. Your program can retrieve those names with the Resource Manager’s GetString function.
Only one of the names is available in systems before System 7: the name set by the Chooser desk accessory. That name is stored in 'STR ' resource ID -16096. With System 7, the Sharing Setup control panel lets the user assign two names for network services: the Owner name and the Computer name.
The Owner name is the name stored in 'STR ' resource ID -16096; it identifies the user of the Macintosh. The Owner name is used by System 7 for two primary purposes: to identify the owner of the system when accessing the system remotely through System 7 file sharing or through the user identity dialog used by the PPC Toolbox (and Apple Event Manager), and to serve as the default user name when logging on to other file servers with the Chooser.
The Computer name (also known as the Flagship name) is the name stored in 'STR ' resource ID -16413; it identifies the Macintosh. The Computer name is the name used by system network services to identify themselves on the AppleTalk network. For example, if your system’s Computer name is “PizzaBox,” the PPC Toolbox registers the name “PizzaBox:PPCToolBox@*” when you start program linking, and file sharing registers the name “PizzaBox:AFPServer@*” when you start file sharing.
Which AppleTalk routines can & can’t be called at interrupt time
Date Written: 6/19/91
Last reviewed: 6/14/93
Can any AppleTalk routines be called at interrupt time? Inside Macintosh says that DDPWrite and DDPRead can’t be called from interrupts. If all higher-level AppleTalk protocols are based on DDP, it seems that they all would not work.
___
The AppleTalk routines you can’t call at interrupt time are the original AppleTalk Pascal Interfaces listed in Inside Macintosh Volume II; these are also known as the “Alternate Interface” AppleTalk routines, or ABPasIntf.
The Alternate Interface routines cannot be called at interrupt time because they allocate the memory structures needed to make the equivalent assembly language AppleTalk call. For example, when the NBPLookup routine is called, it’s passed a handle to an ABusRecord. NBPLookup then has to allocate an MPPParamBlock and move the parameters from the ABusRecord into the newly allocated MPPParamBlock. Then NBPLookup makes a LookupName call, passing it the MPPParamBlock. When LookupName completes, NBPLookup must move results into the ABusRecord and release the memory used by the MPPParamBlock. Since memory is allocated and released within the routine, it cannot be called at interrupt time.
With that out of the way, the calls you can make at interrupt time (with some restrictions listed below) are what Apple calls the “Preferred Interface” AppleTalk routines. Most of the Preferred Interface routines are listed on page 562 of Inside Macintosh Volume V. There are a few additional calls that were added after the publication of Inside Macintosh Volume V; they’re documented in the AppleTalk chapter of Inside Macintosh Volume VI.
The Preferred Interface AppleTalk routines can be made at interrupt time as long as:
• You make them asynchronously with a completion routine (that is, the asynch parameter must be TRUE and you must provide a pointer to the completion routine in the ioCompletion field of the call’s parameter block). Making a call asynchronously and polling ioResult immediately afterward within the same interrupt-time code (which is basically the same as making the call synchronously) is not the same as using a completion routine.
• They are not listed as routines that may move or purge memory. The Preferred Interface routines do not allocate or dispose of any memory, since they’re just high-level ways to make the assembly language AppleTalk calls and are not built upon the old Alternate Interface routines.
X-Ref:
Macintosh Technical Note “Using the High-Level AppleTalk Routines”
Macintosh Technical Note “AppleTalk Interface Update”
Macintosh Technical Note “Avoid Use of Network Events”
AppleTalk and INITs
Date Written: 9/5/91
Last reviewed: 6/14/93
Does AppleTalk work the same with an INIT as with an application? I’m using only Name Binding Protocol (NBP) and Datagram Delivery Protocol (DDP) stuff.
___
Yes! Responder is an example of an INIT that utilizes the NBP to register a Macintosh on the network. NBP requires DDP, so it is also present. AppleTalk is loaded before any INITs, which makes it available to them.
Install AppleTalk with Installer instead of drag-installing
Date Written: 12/3/91
Last reviewed: 6/14/93
We have problems using AppleTalk version 56 on a Macintosh Plus under System 6. The problems go away when we drop AppleTalk version 52 into the System Folder. What’s going on?
___
AppleTalk version 56 isn’t working for you because you just copied the AppleTalk file into the System Folder of your Macintosh with the Finder (this is known as a “drag-install”). All versions of AppleTalk from version 53 up through the current version must be installed by an Installer script. If you drag-install those versions of AppleTalk, several very important system resources won’t be copied into the System file and AppleTalk won’t work.
Apple software products that require AppleTalk version 53 or greater always include the Installer and Installer script that copy all system resources needed correctly. Apple also supplies the source to an Installer script that you can use if you license AppleTalk to ship with your products. See the “AppleTalk Licensing Disk 3.2” folder on the latest Developer CD for a look at the Installer script code. As usual, you’ll need to contact Software Licensing at AppleLink address SW.LICENSE if you want to ship AppleTalk with your products.
Preferred AppleTalk calls and AppleTalk version
Date Written: 1/8/92
Last reviewed: 6/14/93
Do I need AppleTalk version 48 to call AppleTalk routines using the preferred AppleTalk interface?
___
The preferred AppleTalk routines don’t require AppleTalk version 48. You can make any of the AppleTalk calls listed in Inside Macintosh Volume II from a Macintosh Plus. To make .XPP driver calls listed in Inside Macintosh Volume V, you’ll need to use AppleTalk version 48. To make the new AppleTalk calls listed in Inside Macintosh Volume VI (and the Macintosh Technical Note “AppleTalk Phase 2 on the Macintosh”), you’ll need version 53 or later. To make ADSP calls to the .DSP driver, you’ll need to either install ADSP or use AppleTalk version 56 or later which includes the .DSP driver.
Using AppleTalk self-send mode
Date Written: 4/20/92
Last reviewed: 6/14/93
What’s the recommended method for allowing an AppleTalk node to send packets to itself using AppleTalk’s self-send mode (intranode delivery), assuming customers are running various versions of AppleTalk? There used to be a control panel called SetSelfSend that would turn on AppleTalk self-send mode at startup time. Should we use that control panel or should we use the PSetSelfSend function in our program to set the self-send flag ourselves?
___
AppleTalk self-send mode requires AppleTalk version 48 or greater. You can check the AppleTalk version with Gestalt or SysEnvirons. All Macintosh models except for the Macintosh XL, 128, 512, and Plus have AppleTalk version 48 or greater in ROM.
The SetSelfSend control panel is still available on the Developer CD Series disc (Tools & Apps:Intriguing Inits/cdevs/DAs:Pete’s hacks-Moof!:SetSelfSend). However, we don’t recommend it as a solution if you need to use self-send mode in your program. Instead, you should use the PSetSelfSend function to turn self-send mode on with your program.
AppleTalk’s self-send mode presents a problem. Any changes made to the state of self-send will affect all other programs that use AppleTalk. That is, self-send mode is global to the system. Because of this, programs using self-send should follow these guidelines:
• If you need self-send for only a brief period of time (for example, to perform a PLookupName on your own node), you should turn it on with PSetSelfSend (saving the current setting returned in oldSelfFlag), make the call(s) that require self-send, and restore self-send to its previous state.
• If you need self-send for an extended period of time (for example, the life of your application) in which your program will give up time to other programs, you should turn self-send on and leave it on — do not restore it to its previous state! Since other programs running on your system (that aren’t well-behaved) may turn off self-send at any time, programs that require self-send should periodically check to make sure it’s still on with either PSetSelfSend or PGetAppleTalkInfo. Apple’s system software has no compatibility problems with self-send — that is, it doesn’t care if it’s on or off — so leaving it on won’t hurt anything.
Documentation describing AppleTalk 56 and 57 differences
Date Written: 8/14/92
Last reviewed: 6/14/93
What are the differences between AppleTalk 56 and 57 in terms of features, bug fixes, interface, and any technical changes related to driver interfaces?
___
The primary difference between the two versions of AppleTalk involves support for AppleTalk Remote Access, and multinodes. “Multinode” is the capability for a workstation to acquire a node ID separate from that of the workstation user node. AppleTalk Remote Access uses a multinode to provide services for the remote connection via the modem. For more information concerning the differences between the two revisions, there are two documents that you should read. The Macintosh Technical Note “AppleTalk, the Rest of the Story” (formerly #311, “What’s New With AppleTalk Phase 2”) explains many of the changes. You can also read the release notes, located on the Developer CD by this path:
This document discusses many of the bug fixes implemented in the new release.
Different AppleTalk versions OK for nodes
Date Written: 8/14/92
Last reviewed: 6/14/93
Is it OK for different nodes to run different versions of AppleTalk on a network?
___
You don’t need to run the same version of AppleTalk for each node on the network. However, AppleTalk versions 53 and greater support AppleTalk Phase 2, so if you’re working on an application that depends on the Phase 2 support (for instance, using the NBP wildcard character “≈”), you’ll need to use AppleTalk version 53 or later for all nodes running that application.
NW 525 - AppleTalk Remote Access Protocol Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As for this month:
PBRemoteAccess “error = -17”
ARA Developer’s Toolkit documentation fix for variable pb
PBRemoteAccess error = -17
Date Written: 11/19/92
Last reviewed: 6/14/93
We receive an error = -17 from PBRemoteAccess. Why?
___
What this means is that the Remote Access Manager hasn’t been loaded into memory. Loading the Remote Access Manager into memory takes up valuable RAM space. You should do this only when necessary. Usually, this is done just before calling Connect. You can load the Remote Access Manager into memory yourself using the Load command (see page 7 of the ARA Developer’s Toolkit). However, you should really only call Load just before you call Connect. Calling Load before you make the Status call doesn’t really buy you anything. If you do this (and currently no connection is established) you’ll get the -5833 “PORTDOESNOTEXIST” error. This simply means that the Remote Access Manager is loaded but the user port hasn’t been opened—that is, there’s no connection (ARA 1.0 supports one connection through the user port).
Keep in mind also that if you do call Load you must eventually balance it out with an Unload call (see page 7 of the ARA Developers Toolkit). Failure to do so could cause problems. Typically, you’d call Load just before you call Connect, and then after you call Disconnect you’d call UnLoad.
ARA Developer’s Toolkit documentation fix for variable pb
Date Written: 11/19/92
Last reviewed: 6/14/93
In the ARA Developer’s Toolkit manual, at the bottom of page 12, the variable pb is declared as “TRemoteAccessStatusParam.” Shouldn’t this read “TRemoteAccessParamBlock”?
___
Yes, for this specific example pb should be declared as type TRemoteAccessParamBlock. Thanks for pointing out the error.
AppleTalk Remote Access (ARA) password
Date Written: 1/6/92
Last reviewed: 6/14/93
I often connect to a network via AppleTalk Remote Access (ARA) without mounting an AppleShare server (to print, for example). Do I have to mount an AppleShare volume to change my ARA (network, not server access) password or is there another way? Does changing the password associated with the AppleShare volume I’m mounting affect the ARA network access password?
___
Yes, the only way currently to change your AppleTalk Remote Access (ARA) password is via mounting an AppleShare volume or by changing the password as the AppleShare (or FileShare) administrator on the ARA host. The System 7 File Sharing and AppleShare 3.0 file servers, the PPC toolbox, and ARA all share the Users & Groups file, but typically only the AppleShare client gives a way to change the password. Remotely changing the AppleTalk Remote Access password can be accomplished by mounting an AppleShare volume on the ARA host, and changing the password for that specific AppleShare volume. This updates your password in the Users & Groups setup, which is the same one used by ARA (hence the doubly changed password). If you were to mount a volume on a Macintosh other than the ARA Macintosh, this would of course be a separate Users & Groups file, and changing this password would not affect your ARA password.
The Users & Groups libraries in the AppleShare 3.0 Developer’s Kit gives developer applications running on the server machine a way to manipulate the Users & Groups file. It sounds like you’re mostly interested in manipulating your password from a user perspective (rather than writing an application to do it), however, so this may not be all that pertinent to you.
ARAP and PGetAppleTalkInfo bug workaround
Date Written: 2/6/92
Last reviewed: 6/14/93
After connecting to a remote network via AppleTalk Remote Access (ARA) I can call PGetAppleTalkInfo and it returns the proper zone name. However, after disconnecting, PGetAppleTalkInfo still returns the remote network’s zone name instead of “*” or nothing as I would expect. Is there some period of time I should wait before expecting the zone name and network number to return to zero (no internet)?
___
This is, in fact, a bug with ARA version 1.0. Apple is investigating the problem and there will be a fix in a future release. An easy workaround is to check the GetZoneList or GetMyZone call to see if it returns any zones.
Calling ARA Connect without using Remote Access file
Date Written: 4/29/92
Last reviewed: 6/14/93
How can I call Connect in AppleTalk Remote Access without an existing ARA connection file created by the Remote Access application?
___
This isn’t directly possible, because without the ARA connection file your program becomes tied to the underlying link tool. The file was implemented so that in the future, when there are different link tools for the different link types, the program will know the link type and tool, plus associated link-specific data to use. To connect without the ARA connection file requires knowledge of the link tool data structures used by each individual link tool. Because these may change, your code may break.
However, there’s a roundabout way of calling Connect. It requires that you first establish a connection using a document created by the ARA application. Next, make the IsRemote call, setting the optionFlags to ctlir_getConnectInfo (see page 11 of the AppleTalk Remote Access Application Programming Interface Guide). This will cause the information necessary to create the remote connection (connectInfoPtr) to be returned. You would then save this connectInfo data in your application, and when you want to connect sometime later, you would pass this data to the Connect call (in the connectInfo field).
NW 530 - AppleTalk Transaction Protocol Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As this month:
Responder protocol documentation not available
Date Written: 11/5/90
Last reviewed: 8/1/92
Can you please point us to the note that describes the Responder protocol? I recall seeing it documented somewhere.
___
If you have seen any Responder documentation around, it must be bootleg documentation. After talking with the AppleTalk engineers, I was assured that this documentation is not available. Some people wanted it available; others didn’t. Guess who won.
Anyway, the Responder uses ATP (AppleTalk Transaction Protocol) as well as AEP (AppleTalk Echo Protocol) to send/receive data from one machine to another. If you have a copy of Peek and Inter•Poll you can check this out on the network to better understand it. It’s a pretty straightforward implementation. AEP and ATP are documented in Inside AppleTalk. These, coupled with Gestalt or SysEnvirons, to get any machine-specific information you may wish to send, should be all you need to understand how the Responder works.
NW 535 - Datagram Delivery Protocol Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
Datagram Delivery Protocol (DDP) header checksum field
Date Written: 4/2/91
Last reviewed: 6/14/93
Does the Macintosh client pay attention to and validate Datagram Delivery Protocol (DDP) checksums within long DDP packets received?
___
DDP is a client of the AppleTalk Transaction Protocol (ATP), which is a client of the AppleTalk Session Protocol (ASP) and AppleTalk Filing Protocol (AFP). DDP is told by the entity for whom it is a client whether it should use checksumming. For performance reasons, our version of ATP does not specify that DDP use the checksum. Both AppleShare and the AppleShare client are out of the loop; neither can specify whether or not to use the DDP checksum.
The LAP layer performs checksumming, ensuring no on-the-wire corruption. The only benefit of DDP checksumming is end-to-end corruption detection when the packet has travelled over a malicious router that has validly received a DDP packet on one net, changed the packet, re-computed the LAP checksum, and sent it out on another cable. Because of the performance hit of DDP checksumming and the rarity of such a malicious router, it was decided not to request DDP checksumming.
ZIP Query packet zero checksum value
Date Written: 3/3/92
Last reviewed: 6/14/93
Is a zero checksum value indicative of no checksum provided with the Zone Information Protocol (ZIP) packet?
___
True, a zero checksum in any DDP packet with an extended header (including ZIP packets) indicates that a checksum was not performed. See Inside AppleTalk, 2nd Ed. pages 4-17.
How to write a DDP read with completion routine
Date Written: 2/28/92
Last reviewed: 2/28/92
The PWriteDDP call is nothing like a PReadDDP call. We want to do an AppleTalk Datagram Delivery Protocol (DDP) read with a completion routine (to wait for an echo reply), but with only the old style call, this is impossible. Is a completion routine for DDPRead possible?
___
Because of the ABRecord structure handling implemented in the DDPRead call, an asynchronous version of this call was not possible. DDPRead implements Memory Manager calls. As a result, no preferred style of call was implemented for DDPRead. The alternative is to alter your process to use the POpenSkt call instead. As part of the POpenSkt function, you'll need to define a socket listener. A sample socket listener can be found in the Tech Note "AppleTalk Timers Explained" (it’s written in MPW assembly code). In addition, a sample program called DMZ, on the System 7 Golden Master CD, uses that echo socket listener code fragment.
Communication between players in a game on an AT network
Date Written: 12/18/90
Last reviewed: 2/1/91
How can I use the broadcast mode in an AppleTalk DataGram Delivery Protocol (DDP) layer to communicate with the other players of a game that is on a network and not interfere with other network users?
___
The broadcast mode may seem like a solution, but Apple doesn’t recommend using broadcast mode. Applications like games generally end up sending LOTS of update packets to other players of the games. If your program broadcasts those packets, then all nodes on your network will be interrupted for every packet sent and that can cause performance problems on every machine on a network. In Apple supplied software, broadcast mode is only used when packets need to be sent to every node on a network. For example, Name Binding Protocol (NBP) Lookup packets are broadcast because the network address is unknown.
The following suggestions should help implement communications between players.
The DDP protocol layer does not guarantee delivery of packets (the disadvantage), but has very little overhead (the advantage). If you require delivery of all packets and can take a small additional performance hit, you should use the AppleTalk Transaction Protocol (ATP) layer.
The DDP type you use must be in the range of $10-$FF. The DDP type you choose to use (in that range) probably won’t make a lot of difference unless you define multiple clients to DDP within your socket listener. Packets addressed to your socket will get sent to your socket listener. How you use the type is up to you (as long as you stay out of the reserved range).
You should open a dynamic socket (i.e., use 0 for the socket number and use the socket number in the range $80-$FE that is returned) with the OpenSocket call and then register a name on the network for that socket with the RegisterName call. If all copies of the game register with the same NBP type, then you can use the LookupName call to find other players on the network. Once you’ve found other players and decided who you’re going to play against, you just address each DDP packet to the internet address(es) of the other player(s) socket(s). Several multi-player network games I’ve seen on the Macintosh do just that. (Hint: If you limit games to players on a single network, DDP will use short header packets which are slightly faster to send (8 bytes less per packet).)
If you build a table (array) of network addresses from those playing a game, you can use this algorithm to send a packet to each player.
BEGIN
{ put data into buffer for DDP and set the common parameter block fields: }
{ and Destination Network (if limiting play to a single network). }
buildPacket;
FOR Player := 1 to NumberOfPlayers DO
BEGIN
{ Set the Destination Node and Destination Socket fields of the }
{ parameter block to the network address of a player. That address }
{ would be in an array of network addresses (one for each player). }
setAddress(Player);
{ Send the datagram to a player using SendDatagram call. }
doSendDatagram;
END;
END;
NW 540 - AppleTalk Ethernet Driver Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
“Undefined entry” link errors when opening Ethernet Driver
Date Written: 8/8/91
Last reviewed: 6/14/93
When I try to open the EtherNet driver as described in Inside Macintosh Volume VI on pages 32-80 and 32-81, I get the following undefined entry error messages:
The “DisplaySInfo” and “SaveSInfo” are bogus procs that the sample writer
didn’t take out or comment out.
However, SGetTypeSRsrc is a legal Slot Manager trap, IF you are using the new
version of the Slot Manager. The definitions from the latest interfaces
(slots.p, slots.h) are as follows:
FUNCTION SGetTypeSRsrc(spBlkPtr: SpBlockPtr): OSErr;
INLINE $205F,$700C,$A06E,$3E80;
#pragma parameter __D0 SGetTypeSRsrc(__A0)
pascal OSErr SGetTypeSRsrc(SpBlockPtr spBlkPtr)
= {0x700C,0xA06E};
The Slot Manager is dispatched via D0 selectors; there is no glue.
IEEE assigns Ethernet card addresses
Date Written: 9/16/91
Last reviewed: 6/14/93
We need a range of Ethernet card addresses to uniquely identify each Ethernet card we manufacture. We received board IDs and equates from Apple, but not the range of Ethernet addresses.
___
You weren’t sent a range of Ethernet addresses because Apple does not assign them. IEEE is the governing body that you have to contact to get a range of numbers; Apple had to do the same thing to get the numbers for its boards. IEEE will assign you a block of numbers that includes a unique manufacturer’s ID allowing network sniffers to recognize your products.
Apple Ethernet Cable System power requirements
Date Written: 9/17/91
Last reviewed: 6/14/93
Sections 3.1.2 and 3.1.3 of the “Apple Ethernet Cable System Product Family Overview and Interface Descriptions” state that pin 1 provides either 12 V/2.1W or 5 V/1.9 W, and that 5 volts will be made available on pins 7 and 8, if the host can supply greater than or equal to 1.9W @ 5 V. Which models do not have 5 V available on pins 7 and 8, which models have 12 V on pin 1, and which have 5 V on pin 1?
___
All known hosts will provide 5 V at pins 7 and 8. It is absolutely NOT recommended that a Multiple Access Unit (MAU) designer use Voltage Agile (pins 1 and 14) powering to power a 5 V-only MAU. It is anticipated that all friendlynet-compliant hosts will supply +5 V to pins 7 and 8. Third parties desiring a 5 V-only MAU should use these pins.
MAUs using pins 1 and 14 MUST have a DC-DC converter.
Apple doesn’t presently have a product that uses +12 V on pins 1 and 14 but may in the future. As this is an “open standard,” at least one clone maker and several third-party Apple printer and card manufacturers use this interface, and others are expected.
EtherTalk DriverClose function
Date Written: 11/27/91
Last reviewed: 11/27/91
My EtherTalk DriverClose function is never called by the system, so my VBL and interrupt service routines remain active, even though another network device is active. Any ideas or tips on what might be going on?
___
Your findings are as per design. Just because the user decides not to use EtherTalk doesn’t mean that the user no longer wants Ethernet services. For example, the user might be using MacTCP. MacTCP accesses the .ENET driver directly, bypassing the LAP Manager. Should the NetWork cdev close the .ENET driver when the user switches to LocalTalk or TokenTalk while MacTCP is still using the driver, a system crash would likely result.
Ethernet and Quadra systems
Date Written: 12/6/91
Last reviewed: 6/14/93
The Ethernet connection on our new Quadra system is different from the connection on our Macintosh II Ethernet card. Apparently we need to purchase “Apple Ethernet Media Adapters.” We may reconfigure our existing thin-wire Ethernet network. Do you know of any publications describing the latest technology in setting up an Ethernet network? What are the pros and cons of thin coax, thick coax, twisted pair, or other cables? Does Apple manufacture Ethernet Media Adapters? Is there a cable available that plugs directly into the Quadra’s Ethernet port? Does System 7 File Sharing software execute over an Ethernet network? Under System 7, is it still necessary to activate AppleTalk in order to run EtherTalk?
___
Addison-Wesley has just published a book titled, “Planning and Managing AppleTalk Networks” (ISBN #0-201-52345-0). Networking periodicals such as NetWorld are other good resources for learning about current technology and network cabling system vendors. You might also contact N&C vendors directly for specific information.
Twisted pair is cheaper and easier to implement than the other media; however, the supported distance is not nearly as great as for thin and thick-wire media. For backbone connections, Fiberoptic Data Distribution Interface (FDDI), while expensive, handles the highest bandwidth.
Apple manufactures the Apple Ethernet Thin Coax Tranceiver (M0329LL/A), as well as a Tranceiver for UTP (Unshielded Twisted Pair) and an Adapter for Ethernet AUI (Attachment Unit Interface), for adapting to third-party fiber and thick coax transceivers. Each of these transceiver/adapter units has a cable that plugs into the 14-pin connector on the back of the Quadra, the LC Ethernet card, and the new Ethernet NB card (completely different from the older EtherTalk NB card).
System 7 File Sharing works independently of the hardware connection, so it definitely executes over an Ethernet network. Under System 7 AppleTalk still is required for EtherTalk, although it is possible to bypass AppleTalk. For example, MacTCP, running with the NCSA Telnet Software Package, accesses the Ethernet driver software directly.
Selecting alternate AppleTalk driver at system startup
Date Written: 5/3/89
Last reviewed: 6/14/93
I need to know how to set the Macintosh parameter RAM field that controls which alternate AppleTalk driver is used at system startup (for example, EtherTalk).
___
We discourage directly setting the parameter RAM. The Network 'cdev' and the 'adev' device work together to handle this. Each type of AppleTalk connection (other than LocalTalk) must have its own 'adev' file. The construction of the 'adev' file is similar to that of a 'cdev' file. For each type of AppleTalk connection, such as EtherTalk, the 'adev' file must contain the following
resources:
'ICN#'
'STR '
'BNDL'
'FREF'
owner resource
'adev' code resource
'atlk' code resource
The 'adev' and 'atlk' resources are pieces of stand-alone code that reside in the adev file. The 'adev' resource is responsible for handling all control panel interactions with the Network 'cdev'. The 'atlk' resource contains the actual implementation code for the supported AppleTalk connection. When the user selects an AppleTalk connection from the Network control panel, the Network 'cdev ' updates parameter RAM with a value that represents the AppleTalk connection that is currently selected. This value remains in parameter RAM after the user turns off the Macintosh.
More information about this can be obtained from EtherTalk and Alternate AppleTalk Connections Reference, available from APDA.
NW 545 - Link Access Protocol Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As this month:
AppleTalk and VBL task using self-send mode
AppleTalk and VBL task using self-send mode
Date Written: 5/18/92
Last reviewed: 6/14/93
To make all AppleTalk calls asynchronously, I have to split the VBL task in pieces:
- Setselfsend
- check its async finish
- StartLookup
- check its async finish
- Restoreselfsend
- check its async finish
This means that while the selfsend is set to true, other software will be confused when they do a lookup. Also, when the Macintosh is doing I/O on the network, the VBL will set and restore the selfsend flag. Will other AppleTalk calls fail if the SelfSend flag Is set to true, or does selfsend only work on PLookupName?
___
Your method of splitting up the steps of a lookup to yourself during a VBL task using self-send mode is correct, except you needn’t bother restoring the state of self-send since you are giving up time to other processes between calls to your VBL task.
Self-send mode is a global setting and may affect any AppleTalk calls. When the LAP manager is preparing to send a packet, it checks the destination node. If the destination node is its own node address or the broadcast address, then it sends the packet to itself before putting the packet out on the wire. This usually only affects NBP lookup packets because they are sent to the broadcast address. Most other AppleTalk protocols do not broadcast.
Programs using self-send should follow these guidelines:
• If self-send is only needed for a brief period of time, then you should turn self-send on with PSetSelfSend (saving the current setting returned in oldSelfFlag), make the call(s) that require self-send, and then restore self-send to its previous state.
• If self-send is needed for an extended period of time (for example, for the life of your application) where your program will give up time to other programs, then you should turn self-send on and leave it on (don’t restore it to its previous state). Since other programs running on your system (that aren’t well behaved) may turn off self-send at any time, programs that require self-send mode should periodically call PSetSelfSend to make sure self-send stays on. Apple’s system software has no compatibility problems with self-send—that is, it doesn’t care if it’s on or off—so leaving it on won’t hurt anything.
How to tell if LAP Manager is present
Date Written: 12/12/91
Last reviewed: 2/3/92
What’s the recommended technique for telling whether the user has turned off AppleTalk?
___
The best way to determine whether AppleTalk has been turned off is to use the AppleTalk Transition Queue to alert you to .MPP closures. (This is one of the reasons why the AppleTalk Transition Queue was implemented.) The AppleTalk Transition Queue is available only in AppleTalk version 53 or later, and is documented in the AppleTalk chapter of Inside Macintosh Volume VI, starting on page 32-17. There’s also a code snippet, Transition Queue, in the Snippets folder on the Developer CD Series disc.
AppleTalk AOpen and AClose codes 7 & 8
Date Written: 11/1/91
Last reviewed: 11/27/91
What are AppleTalk messages 7 and 8? They’re documented in lapequ.a as:
AOpen EQU 7 ; Open an ATlk
AClose EQU 8 ; Close an ATlk
but what should the adev do with them and what parameters are passed?
___
The AOpen and AClose messages are sent when the .MPP driver is opened and closed, respectively. When the AppleTalk driver is closed, a shutdown message is not sent. Instead, the LAP Manager determines whether an adev is version 3 or greater and, if true, assumes that the adev can respond to the AClose message and sends the message. Conversely, when the .MPP driver is re-opened while the adev is active, the AOpen message is sent to the adev (assuming that the adev is version 3 or greater).
An important note on this matter is that if you modify your adev to version 3, additional selectors must be supported. These new selectors will be documented in a forthcoming Tech Note.
NW 550 - MacTCP Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As in this Technical Note:
OK to abort a MacTCP name resolver call
OK to abort a MacTCP name resolver call
Date Written: 3/9/93
Last reviewed: 6/24/93
Is it possible to abort an outstanding MacTCP name resolver call before it completes? The CloseResolver call description says that “[b]efore the application exits, the CloseResolver call must be made to release memory structures and terminate all outstanding domain name server calls.” The very next sentence says that “CloseResolver must not be called until all outstanding resolver calls have been completed.” Which of these statements is correct? If it’s the latter one, then does that mean that if I make a StrToAddr call and it returns cache fault I have to wait for the result proc to be called before my application can quit? How long is that likely to be?
___
According to the MacTCP name resolver code, CloseResolver will abort any currently executing name lookup. In other words, you don’t have to wait until your name resolver completion procedure gets called if you want abort the call.
Other things to be aware of are that you can’t perform multiple name resolver lookups simultaneously, you can't call the name resolver from interrupt time, and the timeout for name resolver calls is hard-coded to 37 seconds before they’ll complete with an error if no response is received. All of this information is valid as of MacTCP version 2.0.2 and prior releases as well.
Maintaining a listening server socket on the Macintosh
Date Written: 2/1/93
Last reviewed: 6/14/93
On the Macintosh, I need to consistently listen on the same port for incoming connections. This behavior is analogous to the Listen and Accept functionality provided by the industry standard socket interface for TCP on UNIX systems. That is, I listen on a port/socket for incoming connections; when a remote system attempts to connect, a new socket is created representing that connection; and the port/socket performing the listen continues to listen for other connection requests.
When using the TCPPassiveOpen operation under MacTCP, the listen operation doesn’t persist once an incoming connection is established. That is, the stream used to listen for an incoming request becomes the connection with the remote system. Once that connection is established, there’s no stream listening for subsequent connection requests. Is there any way I can keep a listener active at all times? My application needs to have a listener constantly, or at least with as short a window of unavailability as possible.
___
You’re right that with MacTCP’s nonsocket interface there’s no way to maintain a persistent listener using MacTCP. To emulate this functionality, you’ll have to keep more than one listener active at all times. You can do this by queuing multiple TCPPassiveOpen commands asynchronously to the MacTCP driver. How many to queue depends on how fast you expect connections to come in and how quickly you can requeue new opens after connections are made. Three should probably be enough if you expect a relatively small number of connections and you can requeue new parameter blocks as you receive connections.
PBControl is safe to call at interrupt time in this case. Inside Macintosh X-Ref lists it as unsafe because it’s impossible for them to know what kind of driver you might be calling. For a particular driver, calling it at interrupt time might be totally unsafe, totally safe, or safe to do asynchronously only. In the case of MacTCP, it falls under the “safe if asynchronous” category. Any asynchronous calls to it will queue up and wait, so it’s safe to post them from an interrupt or an ASR. However, since there isn’t an ASR event for Notify, I agree that using an ASR isn’t a solution for you in this case.
There is some sample code you might find useful. On the Developer CD, under the path “:Technical Documentation:Sample Code:Snippets:Networking:TCP Server:” you’ll find a sample server that uses TCP.
MacTCP over ARA requires IP Encapsulation service
Date Written: 12/10/92
Last reviewed: 6/14/93
When I dial into my AppleTalk network none of my MacTCP-based software works. I have MacTCP configured with an IP number on the remote machine, and Telnet (a MacTCP-based application) runs fine, but I can’t connect to any of the hosts on the network I’m dialed into. What could be causing this problem?
___
The problem may be because you don’t have a device on the dial-in net to act as a proxy IP Encapsulation service. When you select the AppleTalk icon (such as LocalTalk, EtherTalk, or Dial-In) in the MacTCP control panel, you’re using a MDEV (IP Link layer) that encapsulates the IP data into an AppleTalk packet and sends it out. You therefore need to have something on the other side that will break out the IP data from the AppleTalk packet and send it out as an IP frame on the network you’re dialed into.
There are several third-party solutions to this problem, the Shiva FastPath and Cayman Gator Boxes being the most common. The feature is normally called IP Encapsulation or KIP. If you use MacTCP this way, you must select the zone via the pop-up menu in the MacTCP control panel that the IP Encapsulation device is in. You must also configure the IP Encapsulation device to give out IP numbers, and set the remote Macintosh to “Server” IP addressing in the MacTCP control panel.
Note: Two Macintosh systems using IP Encapsulation should be able to communicate peer to peer, but they won’t be able to contact non–IP Encapsulation devices.
Definition: IP Encapsulation: The act of taking IP data frames (packets) and placing them inside an AppleTalk packet for transport over an AppleTalk-only media (also known as LocalTalk and ARA). Also known as KIP or KSTAR, which are both names left over from the Kinetics FastPath.
MacTCP ARP limits are hard-coded
Date Written: 9/22/92
Last reviewed: 6/14/93
Is it possible to increase ARP cache size? It appears that MacTCP has memory to cache 35 to 40 entries. If my application sends out IP requests periodically to about 40 unique IP stations, MacTCP drops some entries, and makes an ARP request. Is there any way to program the cache size to a higher limit?
___
Unfortunately, the number of ARP table entries is hard-coded to 20 in the MacTCP source code, and the ARP time-out for aging entries out of the ARP cache is also hard-coded to 10 minutes. There’s no way to change these values, since they are in the code as #defines and used throughout.
How to cancel transactions under MacTCP
Date Written: 12/7/90
Last reviewed: 8/1/92
How do I cancel transactions (specifically connect requests) under MacTCP? I know that I can specify a timeout; however, I would like the user to be able to hit ‘Command-.’ if the transaction’s tired of waiting. I tried KillIO but that seems to crash.
___
Since MacTCP uses the Control call instead of reads and writes, the killio call is not supported to abort a transaction. You should use Abort and Release. Abort terminates the connection and Release releases the stream. As an alternative, a TCPPassiveOpen could be cancelled by issuing an active open from the same machine on the listening port.
Porting a TCP/IP application to the Macintosh
Date Written: 3/19/91
Last reviewed: 8/1/92
We need the following to port our mainframe front-end application to the Macintosh:
• a C++ compiler compatible with AT&T 2.0 (and ANSI C)
• a TCP/IP library with an Application Programming Interface (API) similar to sockets
• an Ethernet card
___
MPW C++ is based on AT&T CFront 2.0. For information about CFront 2.0, please refer to the UNIX System V AT&T C++ Language System Release 2.0 Product Reference Manual.
Sockets is the general UNIX (Berkeley) API for TCP/IP programming. Apple currently offers some libraries that allow you to work with MacTCP but not APIs similar to sockets. Third-party socket libraries for MacTCP are available, however. Also, universities such as the University of Toronto provide public domain socket wrappers for MacTCP.
Ethernet cards are available from a number of sources, including Apple’s Ethernet cards.
MacTCP gateway address and subnet mask fields
Date Written: 5/7/91
Last reviewed: 6/14/93
What are the MacTCP Subnet Mask and Gateway Address fields used for?
___
In the TCP/IP protocol, there are a couple of provisions for simplifying the addressing scheme for smaller local networks. One of these is the subnet mask. It allows the sender to identify the destination machine by a shorter address, which is long enough to distinguish all the machines on the local network. This mask is made up of four octets, and is used as a bitwise mask to show how many bits are being used to specify the network number, subnet number, and node. The gateway address field specifies the IP address of the local network’s router. Packets destined for another network are sent to this router, which then transmits the packets to other networks.
Communicating different processes on the same Mac with MacTCP
Date Written: 6/5/91
Last reviewed: 8/1/92
Is it possible to have both the source and the destination application on the same machine if they are using MacTCP to communicate? If so, what should I do to make sure both applications share the processor so this works properly?
___
It is possible to use MacTCP to communicate to different processes on the same Macintosh computer. Unlike PPC, MacTCP does not bypass the network for same-machine connections, so there is still some “network traffic” involved.
As far as “sharing” the processor goes, this is very important in what you are doing. Here’s a brief outline of what you need to do:
• Make asynchronous MacTCP driver calls;
• If you want to use polled I/O, you can wait for ioResult < 1 to tell when the call completes. Otherwise, you may want to have a completion routine which queues completed calls for processing at event time; or
• Call WaitNextEvent or EventAvail while waiting for driver calls to complete (this gives time to the other MacTCP applications).
For a good reference on using “idle procs” to give time to background applications when using MacTCP, refer to the article, “MacTCP Cookbook” in develop, Issue 6 and get the “NewsWatcher” source code from the Developer CD Series.
How to tell how many of StrToAddr’s network addresses are valid
Date Written: 8/30/91
Last reviewed: 6/14/93
Using StrToAddr, you can receive up to four IP network addresses returned by the service for the host requested, but the MacTCP Programmer’s Guide does not say how to tell how many of the addresses are valid. According to the name resolver code, MacTCP zeros out 4 long words before the StrToAddr lookup and then fills in the addresses it finds. This means that the array contains at most 4 addresses, and is terminated by a zero address (0.0.0.0) if fewer than four addresses are returned.
MacTCP resolver code is in domain name resolver
Date Written: 9/17/91
Last reviewed: 6/14/93
Is the MacTCP resolver code contained in the domain name resolver (DNR)?
___
The resolver code is contained in the MacTCP DNR, as well as in the MacTCP control panel. The DNR code is stored as a resource file in the System folder and is read into memory as necessary in order to convert host names into addresses. It is used in conjunction with a domain name server or with the local hosts file.
MacTCP Hosts file location and function
Date Written: 9/17/91
Last reviewed: 6/14/93
Where should the MacTCP Hosts file be located, and who looks for that file?
___
According to the MacTCP 1.0 Documentation Kit (APDA #M0217LL/A), the Hosts file should be located in the user’s System Folder. The file maps machine names to internet addresses, providing the same service as the domain name server. The Hosts file can be used if you have no domain server on your network. It is also suggested that this file be used for frequently used name-to-address mappings. Instructions on setting up the file are included in the MacTCP documentation.
MacTCP “obtain address” options
Date Written: 9/24/91
Last reviewed: 6/14/93
Under MacTCP, what is the significance of the “obtain address” options, with
respect to (1) manually, (2) server, and (3) dynamically?
___
According to the MacTCP 1.0 Documentation Kit (APDA #M0217LL/A), “obtain address” means the following:
• Manually: You will need to fill in some or all of the fields in the IP Address box;
• Server: The Internet Protocol (IP) address for the user Macintosh is automatically obtained from a server every time the user Macintosh boots up. This option requires
- a Reverse Address Resolution Protocol (RARP) or Bootstrap Protocol (BootP) server on an Ethernet, or
- a Datagram Delivery Protocol–to–Internet Protocol (DDP-IP) gateway on an AppleTalk network that’s compatible with the Kinetics Internet Protocol (KIP) developed at Stanford (also called “IPTalk”), such as the Shiva Fastpath or Cayman Gatorbox
• Dynamically: The node portion of the IP address for the user Macintosh is set dynamically every time the user Macintosh boots up. With this option you still need to set some of the fields in the IP Address Box. All these processes are described in further detail in the MacTCP documentation.
MacTCP and SLIP
Date Written: 11/6/91
Last reviewed: 6/14/93
Does MacTCP actually support SLIP? If not, does Apple plan to provide SLIP support in the future. Does anyone know of any company that does a SLIP for the Macintosh?
___
SLIP is an asynchronous, serial line protocol developed for running TCP/IP over serial communications lines in a point-to-point configuration. SLIP was developed to transmit IP packets over low-speed, sometimes noisy, asynchronous communications lines where error recovery and an efficient line protocol are needed. The SLIP protocol is now being replaced with a new serial line protocol named “PPP,” which uses a more efficient means of establishing a point-to-point IP connection.
MacTCP includes hooks that let you write different link-layer modules. This makes possible the development of interfaces to SLIP, PPP, and to any other link layer that someone may need, like broadband, X.25, and FDDI. Apple does not currently provide support in MacTCP for SLIP or any other serial line protocol. There are, however, several third-party SLIP extensions available for use with MacTCP.
MacTCP StrToAddr and header’s hostInfo record structure
Date Written: 12/12/91
Last reviewed: 6/14/93
I'm using MacTCP v1.1 with Think C, and when calling StrToAddr with hostname = "90.25.3.240", the returned addr field has the following:
addr [0] = 0X00005A19
addr [1] = 0X03F00000
The correct answer should be addr [0] = 0X5A1903F0. What’s the problem?
___
The StrToAddr problem you are experiencing is related to a shortcoming in the header files. The structure for the hostInfo record you are accessing (from AddressXlation.h)is as follows:
typedef struct hostInfo {
int rtnCode;
char cname[255];
unsigned long addr[NUM_ALT_ADDRS];
};
The problem with the way the structure is defined is that rtnCode is defined as an “int.” The size of an int is dependent on your development environment. In MPW, ints are 4 bytes, while Think C uses 2 byte ints as its default. If you’re using Think C, you will see the addresses shifted forward in the storage by 2 bytes, since the rtnCode structure causes the rest of the struct to be shifted forward in memory.
If you’re using Think C 5.0 or later, you can either check the “Use 4 byte ints” check-box in the preferences, or you can change the header files to use “long” in place of “int” (a Think C long is the same size as an MPW int). A set of header diffs for Think C compatibility with MacTCP is on the latest Apple Developer CD Series disc in Tools & Apps: Networking & Communication: MacTCP 1.1 DTS Header Changes.
MacTCP EnumCache data enumeration sequence
Date Written: 12/12/91
Last reviewed: 6/14/93
Does MacTCP's EnumCache name resolver call return the data in a particular order or randomly?
___
Since the EnumCache documentation doesn’t specify any particular sequence for name resolver cache enumeration, it’s best to play it safe and not assume any particular order for the data returned by the call. Since the internals of the name resolver may change in the future, you probably don’t want to rely on any undocumented data ordering assumptions. If you want the entries separated, the best way probably would be to have a dynamically-sized array for each of the entry types (such as addresses, HInfo, and name servers) and fill them in the EnumCache callback.
MacTCP addressing modes and Shiva Fastpath
Date Written: 1/6/92
Last reviewed: 6/14/93
When I attempt to connect to a LocalTalk net using MacTCP 1.1, after opening the MacTCP driver, this error occurs: “Error opening driver / Error in getting address (-23004)”. I’m running System 7.0 on a Macintosh IIci with Shiva Fastpath 4.0, and I’ve configured TCP Admin as follows:
Indicate Resident Zone
Click More
Dynamic addressing
Range 1 to 65534
Enter Gateway Address (address of Fastpath for resident zone)
Enter Domain Name & Address
___
The Fastpath won’t work with MacTCP configured to use dynamic addressing. You need to set MacTCP to use server-based addressing. If you change this setting, and the FastPath is configured correctly, you should be up and running.
MacTCP 1.1 and sending urgent data per RFC 1122 or 793
Date Written: 4/7/92
Last reviewed: 6/14/93
MacTCP 1.1 packets containing “urgent data” have the so-called “urgent pointer” set according to RFC 1122. All our TCP/IP hosts expect a behavior corresponding to RFC 793, however. Is there a possibility to configure MacTCP to this effect?
___
MacTCP can send urgent data according to either RFC 1122 or RFC 793; however, it is not a setting in the driver that determines this. When a programmer makes the TCPSend call, he sets a flag in his parameter block that indicates whether or not to use urgent data, and which version of urgent data to use. Therefore, you would have to modify the program that you are using to set up the parameter blocks appropriately.
To send urgent data using the non-compliant RFC 793 method, set the urgent flag in the TCPSend parameter block to 2. Any other nonzero value in the urgent flag indicates the RFC 1122 method should be used.
MacTCP 1.1 ICMP echo request documentation bug
Date Written: 2/13/92
Last reviewed: 6/14/93
I’m trying to use the ICMP echo request function described on page 88 of the MacTCP Developer’s Kit 1.1 manual to 'ping' a TCP host before trying to open a connection. The problems I’m having seem centered around the ICMPEchoNotifyProc. If I declare the proc as
the proc gets called and the ICMPParamBlockPtr is valid. But after the proc returns, my Macintosh crashes. Can you give me any suggestions as to how to make this puppy work?
___
You’ve found a “bug” in the manual. The ICMPEchoNotifyProc is actually defined as:
The definition is correct in <MiscIPPB.h>. Note that in this definition, the proc uses C, not Pascal calling conventions. In C, the caller removes the parameters from the stack, not the callee, so since your routine has already removed the parameters before returning, they are removed twice, corrupting the stack. Changing your procedure to use C calling conventions should fix your problem.
MacTCP 1.1 & 1.0.1 compatibility
Date Written: 2/13/92
Last reviewed: 8/1/92
We have implemented a TCP/IP product using MacTCP Development Kit version 1.1. If MacTCP version 1.0.1 is installed, will there be any compatibility problems with our implementation.?
___
There are only a very few new calls in MacTCP 1.1 that aren’t in the 1.0.1 driver. Among these are:
• Name resolver HInfo and MXInfo calls
• UDP multi-port sends and receives
• ICMP echo protocol support
As long as you’re not using any of these features, any program developed for MacTCP 1.1 will work with 1.0.1.
MacTCP 1.1 header file incompatibilities and fixes
Date Written: 9/30/91
Last reviewed: 8/1/92
MacTCP 1.1, Apple’s System 7-compatible version of MacTCP, fixes several problems in earlier releases, but doesn’t address several header file incompatibilities. This short note outlines the MacTCP 1.1 header file problems, but it does not include the fixes. Patches in the form of MPW “compare” output are available on Apple’s latest Developer CD Series disc. The new headers are available as part of the “MacTCP Developers’ Kit,” available from APDA (part #M0704/C).
Each header problem is described below, organized by file(s) containing the problem and classified as a general bug or shortcoming, a Think C incompatibility, or a C++ incompatibility. NOTE: The changes have not been thoroughly tested, so use them cautiously.
Problems affecting all header files:
• General problem: Each header file is missing the
#ifdef __cplusplus
extern "C" {
#endif
and
#ifdef __cplusplus
extern "C" {
#endif
which are necessary for C++ unmangling.
• General problem: There are no #ifdefs to prevent including a file multiple times, as in other Apple headers. This was fixed by adding the following to each of the header files:
#ifndef __MACTCPCOMMONTYPES__
#define __MACTCPCOMMONTYPES__
...
#endif
where “MACTCPCOMMONTYPES” is replaced by the name of the header file.
• Think C problem: Think C before 5.0 does not support pascal typedefs, which MacTCP makes use of, so #ifdef THINK_C was added in several instances to declare these pascal typedef functions as type ProcPtr. This fixes the problem.
GetMyIPAddr.h problem:
• General problem: ParamBlockHeader is used as a #define here, conflicting with its use in <Files.h>. The solution is to change the name of the #define to IPParamBlockHeader.
MiscIPPB.h problems:
• General problem: ParamBlockHeader is used as a #define here, conflicting with its use in <Files.h>. The solution is to change the name of the #define to GetIPParamBlockHeader.
• General problem: The structure IPParamBlock is defined in this file with a different definition from the one in GetMyIPAddr.h. The solution is to change the name of the struct.
• General problem: AppleTalk.h is required for successful compilation. Code was added to include this if it has not already been included.
• General problem: icmpEchoTimeoutErr is defined in MacTCPCommonTypes in addition to being defined in MiscIPPB.h. Solution is to remove its definition here.
AddressXLation.h problems:
Think C incompatibility: The “int” type is used within the “hostInfo” structure definition. The default size of an int is different from Think to MPW. In all cases, int in the MacTCP headers should be changed to long.
• Think C incompatibility: The returnRec struct uses an int. Fix is to change to a long as above.
• Think C incompatibility: The CloseResolver() prototype is defined with an empty parameter list, not with a void parameter list. Think C requires the void to consider the definition a prototype. The fix is to add the void keyword as the function parameter list.
• C++ incompatibility: The cacheEntryRecord struct uses a variable named “class”. This causes major problems with C++ compilers, since the class keyword takes on a different meaning in this instance. The fix is to change this to “cacheClass.”
dnr.c problems:
• General/Think C problem: The typedef for OSErrProcPtr was incomplete, causing ambiguity for argument casting. This was changed to "typedef OSErr (*OSErrProcPtr)(long,...);" to make sure the first parameter to the name resolver calls is passed as a long.
• Think C incompatibility: Defines in Think default to short, not long, so all name resolver calls are made incorrectly. This is fixed by the typedef in above, but Think 4.0.5 does not recognize partial prototypes correctly. The fix is to add a “L” to the end of each of the name resolver command #defines.
• Think C incompatibility: The MXInfo() procedure has an extra semicolon after the trailing brace “};” which causes a syntax error with the Think C compiler. The semicolon was removed to fix the problem.
No Pascal headers for MacTCP
Date Written: 3/19/92
Last reviewed: 6/14/93
I want to access MacTCP in a Pascal program. Do you have the C parameter block definitions available as Pascal records or will I have to do my own translation?
___
Unfortunately, Pascal header files and interfaces are not available for MacTCP. If you want to use Pascal, you’ll have to translate the interfaces.
One problem you will run into is that all MacTCP routines and callbacks (those in dnr.c/dnr.o, for example) use C calling conventions. You’ll still be able to call the dnr routines by declaring them as external C functions, as described in the MPW Pascal documentation, but you’ll still have to write any callback functions in C or Assembler, since the Pascal compiler can only call a function using C conventions, but you can’t declare a Pascal function to have C conventions.
X-Ref:
MacTCP Programmer’s Guide, Chapter 4, page 47
MacTCP Type of Service documentation fix
Date Written: 4/21/92
Last reviewed: 7/13/92
Are MacTCP’s Type Of Service (Reliability, Low Delay and Thruput) bit settings swapped in the documentation?
___
The bit settings in the MacTCP programmer’s documentation are reversed for the Type of Service constants. This will be fixed in a future version of the manual. The bit settings should be as follows:
Type of Service Byte (3-bit field)
Bit 0 set for low delay
Bit 1 set for high reliability
Bit 2 set for high throughput
If you wish to correct these settings they can be found on page 35 of the MacTCP Programmer's Guide.
MacTCP ULP timeout documentation fix
Date Written: 5/5/92
Last reviewed: 7/13/92
In the MacTCP Developer’s Kit (Version 1.1) there is a ULP timeout action field which is used in several PowerBook calls to MacTCP. For some calls, zero indicates an abort and nonzero indicates a report. TCPSend, TCPClose and TCPStatus are this way. For other calls, the reverse is documented (0 indictes report and 1 indicates abort). TCPActiveOpen and TCPPassiveOpen are this way. Can I believe the documentation or are there errors in it ? If there are errors, what is the correct way it should be ?
___
According to the MacTCP source code, and you’re right, the documentation is incorrect. For each of the calls with a ULP timeout action, the correct values are:
1 = abort
0 = report only
Macintosh Communications Toolbox MacTCP tools
Date Written: 6/10/92
Last reviewed: 9/15/92
My application uses the Macintosh Communications Toolbox and ADSP to connect to network services. What software do I need to get to make the same connections using TCP/IP? MacTCP or other recommendations?
___
Apple only makes one MacTCP Communications Toolbox tool that works specifically with MacX and TCP/IP (the TCP Tool). This tool is not supported for use by third party developers. For CTB/MacTCP connection tools which are supported, you need to get a third-party CTB MacTCP tool. These are available from several vendors. For example, TCPack from ASC (Advanced Software Concepts) is a set of Connection Tools designed to allow simultaneous TCP/IP connections using Apple’s MacTCP driver. All Apple’s terminal tools (asc3270, asc5250, …), the Apple standard terminal tools (TTY, VT100, VT320), as well as several third-party terminal tools can be used to enter terminal sessions with TCPack. TCP/Tools from InterCon Systems is another package which allows you to use existing CTB applications to log onto Unix workstations using your LocalTalk or EtherTalk network.
NW 560 - Macintosh Protocol Package Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As this month:
Retries and tickle mechanism for nonAppleShare connections
Retries and tickle mechanism for nonAppleShare connections
Date Written: 12/28/92
Last reviewed: 3/1/93
We’re experiencing time-outs in the .MPP driver communications between our non-AppleShare server and applications that talk to it, when the connection is low-speed (for example, an AppleTalk Remote Access connection). We have no problems over local area nets or with AppleShare connected over our low-speed connection. What values should we use for the ATP timeOutVal and retryCount?
___
The reason you don’t see problems with AppleShare connections is that AppleShare uses the AppleTalk Filing Protocol (AFP) and AFP is built on the AppleTalk Session Protocol (ASP). ASP uses an infinite retry count on its ATP transactions and a tickle mechanism to detect broken session connections. If ASP’s tickle mechanism finds the session connection is dead, it kills all outstanding asynchronous ATP calls with PKillSendReq and PKillGetReq. ASP clients don’t have to worry about time-out conditions except when the network connection fails.
The AppleShare workstation determines the timeOutVal to pass to AFP/ASP by using the Apple Echo Protocol. Here’s how you could use the echo protocol to determine the timeOutVal for your program:
1. Send the other end of the new connection a full-size (586-byte) packet to the echo socket.
2. Wait for up to 10 seconds for the echo packet to come back. This should be enough time to send a full-size packet both ways at 1200 bps (slower than any connection you’d hope to encounter on an AppleTalk network).
3. If the echo packet isn’t back in 10 seconds, assume the packet was lost either going to or coming from the other end and use a default retry time of 4 seconds (this is what AppleShare uses as a default when its echo packet is lost—it’s generally a good value for LocalTalk).
4. If the echo packet is back within 10 seconds, multiply the turnaround time by 4.5 (enough time to transfer nine full-size packets).
5. Add the maximum amount of latency you expect the responding side of the connection to have between receiving a request and sending the response (you’ll have to determine this value by running your code on a slow system).
6. If the calculated value ( (echo time * 4.5) + latency ) is greater than 2 seconds, use it. Otherwise use a minimum default retry time of 2 seconds. The reason for keeping the minimum above a certain level is to minimize network traffic.
We recommend building a session protocol something like ASP on top of ATP so that you can use infinite retries and let a tickle mechanism tear down a broken connection. A tickle mechanism is also easy to implement. For example, to implement a tickle mechanism like the one AppleTalk protocols use, just start a VBL task with a vblCount of 2 minutes (120 ticks) on both ends of the connection. Every time you receive a packet of any kind from the other side of the connection, reset the vblCount to 2 minutes again. If the VBL task ever gets called, the connection was broken. To send the tickle packets, just call PSendRequest (or PNSendRequest) to send a small tickle request with an infinite retry count and a retry period of 30 seconds. Whenever you receive a tickle packet from the other side of a connection, simply ignore it (if you don’t respond, ATP will keep retrying every 30 seconds, which is what you want).
If you don’t want to use a tickle mechanism, you’ll have to decide how many times you want ATP to retry. The value you use should balance how long you want a user to wait for something to happen and how reliable the user’s network is at delivering packets — something that isn’t at all easy to determine.
For more information, see the Macintosh (Networking) Technical Note “AppleTalk Timers Explained.”
MPP stands for Macintosh Protocol Package handler
Date Written: 2/28/92
Last reviewed: 2/28/92
What does “MPP” stand for? We know it’s a lower-level driver that contains code to implement ALAP (Link Access Protocol), DDP (Datagram Delivery Protocol), NBP (Name Binding Protocol), and RTMP (Routing Table Maintenance Protocol) stuff, but we’re curious to the point of not being able to do any work :) Macintosh Packet Protocol? Multiple Problem Protocol?
___
MPP stands for Macintosh Protocol Package handler. XPP stands for eXtended Protocol Package handler; ATP stands for AppleTalk (originally AppleBus) Transaction Protocol handler; DSP is Data Stream Protocol handler; LTM is Link Tool Manager; and MNP is Microcom Networking Protocol, implemented by AppleTalk Remote Access across the remote link. Hope you can get some work done now ;)
RAM-based AppleTalk driver fixes Mac Plus PNSendRequest error
Date Written: 1/1/91
Last reviewed: 1/1/91
I get an odd address error when using PNSendRequest on the Macintosh Plus. The Macintosh Plus has version 19 of the .MPP driver. Is there is an INIT or something that patches the older Macintosh models with the newer drivers?
___
Inside Macintosh suggests checking the .MPP driver version to see if the new driver is available (version >= 48).
You need the RAM-based AppleTalk drivers on the older Macintosh models to use the calls documented in Inside Macintosh Volume V. The RAM-based AppleTalk driver is available as an AppleTalk System file, and you need to place it in the System Folder of your Mac Plus.
X-Ref:
“The AppleTalk Manager,” Inside Macintosh Volume V
PKillNBP aKillQEl pointer
Date Written: 6/12/92
Last reviewed: 9/15/92
Where can I get the Q element pointer for a PLookupName call in order to call PKillNBP?
___
The pointer that you pass in the parameter block to PKillNBP, is the pointer to the parameter block of the outstanding lookup request. If several lookup requests have been made asynchronously, and are outstanding, then you would take the pointer to each parameter block and issue separate PKillNBP calls for each lookup to kill the request on.
Each asynchronous lookup request along with other asynchronous requests to the drivers get queued for processing. The KillNBP request takes the pointer to the parameter block of the outstanding request and searches through the driver queue, looking for a match. When a match is found, the request is dequeued and the driver notified of the action. If the request has already been dequeued—for example, if the original lookup request was completed while the PKillNBP was made—a cbNotFound error (error -1102) will be returned.
NW 565 - Name Binding Protocol Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
Macintosh NBPLookup badUnitErr conditions
Date Written: 11/14/90
Last reviewed: 2/8/91
Why am I getting a badUnitErr as a result code from NBPLookup? This error is not listed as a result code for NBPLookup, nor anywhere in the AppleTalk Manager.
___
You’re probably getting the badUnitErr result because you don’t have the AppleTalk drivers open. Since AppleTalk calls are made to a device driver (the AppleTalk driver), you can get back general operating system errors from the driver.
See the Macintosh Technical Note “Opening AppleTalk” for a description of how to open the AppleTalk drivers.
AppleTalk 56 NBP reply packet entity field checks
Date Written: 6/14/91
Last reviewed: 6/14/93
As stated in Inside AppleTalk, each entity field in an NBP reply packet can be a maximum of 32 characters. In previous versions of AppleTalk, no range checking was done on entity field lengths, and often names that were too long were used, which eventually caused a crash somewhere else in the protocol stack.
Likewise, a null character in the object field of an entity has never been OK; it just happened to work because no range checking was done. (The only place that a null can legally be used in an NBP tuple is in the zone name field of an NBP LkUp, FwdReq, or BrRq packet; see page 7-17 of Inside Appletalk for more information.)
Now, under Appletalk 56, a range check is done on each entity field to ensure that the length is legal (1<=length<=32). When it finds a packet that contains a “corrupt” entity name, that packet is discarded.
Name Binding Protocol (NBP) interval and count fields
Date Written: 9/13/91
Last reviewed: 10/8/91
Is there a limit on the values set in the Name Binding Protocol (NBP) interval and count fields when used with PLookupName and PConfirmName calls? How do the interval and count work? If a device is not on the network and I send a PLookupName with interval = 20 and count = 20, will I wait 400 seconds before PLookupName returns?
___
Since the interval and count parameters for NBP calls are both 1-byte, the values used are limited to the range of 0-255 ($00-$FF). Here’s what the values do:
• interval = retransmit interval in 8-tick units. This value is used to set up a VBL task. A value of 0 should not be used because that would mean the VBL task would never be executed and would be removed from the VBL queue.
• count = total number of transmit attempts. Each time the interval timer expires, this value is decremented by 1. When it reaches 0, the NBP call completes. So if a value of 0 is used, the packet will be retransmitted 255 times (or transmitted 256 times).
Three things can happen to make the LookupName, RegisterName, or ConfirmName calls complete:
• PKillNBP can be called to abort one of the calls (see Inside Macintosh Volume V, page 519).
• maxToGet matches are returned or the return buffer is filled. Here’s how this works: Each time an NBP lookup reply (LkUp-Reply) packet is received, an attempt is made to add all the NBP tuples found in that LkUp-Reply packet to the return buffer. If all the tuples cannot be added to the buffer because there isn’t enough room, the call completes with as many tuples as could fit and the numGotten field will contain the number of matches in the buffer. If all the tuples from the LkUp-Reply packet are added to the buffer, numGotten (the number of matches in the buffer) is compared to the value passed in the maxToGet field. If numGotten is greater than or equal to maxToGet, the call completes and the numGotten field will contain the number of matches in the buffer. Since the buffer can fill before maxToGet matches are received and since LkUp-Reply packets can return multiple tuples, you may get more or fewer matches than you asked for with maxToGet.
• The count is decremented to 0. You can use this equation to determine how long the call would take to complete this way:
IF count = 0 THEN count := 256;
TimeToCompleteInTicks := count * interval * 8;
The RegisterName and ConfirmName calls always complete after they receive the first LkUp-Reply packet to their request, so you could look at them as always having a maxToGet of 1 (maxToGet is not one of the parameters for those two calls).
AppleTalk PLookupName interval and retry values
Date Written: 1/6/92
Last reviewed: 1/27/92
What are recommended values for retry interval and retry count when using the AppleTalk NBP call PLookupName on a complicated internet?
___
You might want to start with the NBP retry interval and retry count values Apple uses for its Chooser PRER and RDEV device resource files. The Chooser grabs these values from the PRER’s or RDEV’s GNRL resource -4096:
Device Interval Count
-------------------------- -------- -----
LaserWriter $0B $05
AppleTalk ImageWriter $07 $02
AppleShare $07 $05
If no GNRL resource $0F $03
Apple’s engineering teams found these values to work well in most situations.
The count value should be based on how likely it is for the device to miss NBP lookup requests. For example, the AppleTalk ImageWriter has a dedicated processor on the LocalTalk option card just to handle AppleTalk, so its count value is low; most Macintosh models and LaserWriter printers depend on their 680x0 processor to handle AppleTalk along with everything else in the system (the Macintosh IIfx and Macintosh Quadra models are exceptions to this), so their count value is higher.
The interval value should be based on the speed of the network and how many devices of this type you expect there to be on the network. On a network with very slow connections (for example, one using a modem bridge), or in cases where there are so many devices of a particular type that lots of collisions occur during lookups, the interval value should be increased.
Apple puts these values in a resource because not all networks and devices are alike. You should do the same (put your interval and count in a resource so that it can be configured).
Don’t access the MPW NBP EntityName field directly
Date Written: 1/1/91
Last reviewed: 6/14/93
When I fill in the fields of MPW’s Name Binding Protocol (NBP) EntityName structure, AppleTalk doesn’t recognize the entity, even though I know it’s out there. What’s going on?
___
The real definition of EntityName is 3 PACKED strings of any length (32 is an example). No offsets for Asm are specified since each string address must be calculated by adding the length byte to the last string pointer. In Pascal, String(32) will be 34 bytes long since fields never start on an odd byte unless they are only one byte long, so this will generate correct-looking interfaces for Pascal and C, but the interfaces will not be the same. This is OK since they are not used.
The point is that you should never try to access the fields of the EntityName field directly. The only reason the type is defined at all is so that you can allocate EntityName variables that will hold the largest possible EntityName. To fill in an EntityName record, you call the NBPSetEntity routine.
NW 570 - Printer Access Protocol Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
Monitoring PAP packets with AppleTalk Peek
Date Written: 8/7/90
Last reviewed: 8/30/90
Are there hardware or software tools for monitoring AppleTalk Printer Access Protocol (PAP) packets in some direct way?
___
A tool called “AppleTalk Peek” allows you to monitor packets that are being sent over AppleTalk. It is available on the AppleLink and on the latest Developer CD Series disc. You can find the tool via the following path: Storage and Communication Folder : Network Folder : AppleTalk Tools Folder. This tool might enable you to determine experimentally, PostScript handle sizes that work best for your application.
Using PAP & code for finding printer driver under System 7
Date Written: 6/6/91
Last reviewed: 8/1/91
Is there any documentation or sample code on the Printer Access Protocol (PAP), besides Inside AppleTalk and MacTutor’s sample? Or is there a better way to shove 1 MB and larger files down the pipe to a PostScript device?
___
The question that you ask has become a popular one these days; it seems that a lot of people are writing PAP programs. Unfortunately, there isn’t really a clean-cut answer. There are several options:
1) The code that appeared in MacTutor seems to work just fine. Of course, it is unsupported by Apple and it may very well break under a future system software release. It is definitely the quickest way to get a PAP-based program coded.
2) You could write your own PAP interfaces. This is a very time consuming operation, but it also most likely not to break under future systems. Other companies have done it, and it is fairly straightforward.
3) Through software licensing, you can license a library named papworkstation.o. It is a library only, with little or no documentation, and it is unsupported. It is, however, used by several third parties, and it works OK.
In case you do use the MacTutor code, the following example shows a method for finding the printer driver under System 7:
FUNCTION GetPAPDriver: BOOLEAN;
VAR
theResFile: INTEGER;
theWorld: SysEnvRec;
theError: OSErr;
DoinFolders: BOOLEAN;
myFeature: LONGINT;
sysVRefNum: INTEGER;
sysDirID: LONGINT;
gotDriver: BOOLEAN;
numStr: Str255;
BEGIN
gotDriver := TRUE;
DoinFolders := FALSE;
(*--------------------- The 7.0 Way! --------------------------*)
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
Receiving RTMP packets from a generic router
Date Written: 4/22/91
Last reviewed: 6/14/93
I’m trying to receive the periodic Routing Table Maintenance Protocol (RTMP) packets sent out from a generic router. The only solution so far is to close down the Link Access Protocol (LAP) handlers and install my own. However, when I’m finished, I must restart AppleTalk when my program exits. Is there an alternative solution?
___
You’ve hit upon a side effect of the AppleTalk architecture. It’s understandable that being only a listener, that you would simply want to attach yourself into the LAP chain without shutting down AppleTalk. Your findings are correct though—you would need to shut down the LAP handler and install one of your own. This would require restarting AppleTalk when your program exits.
You’d find that EtherPeek, a commercially available software sniffer works similarly. This has the ramifications of complicating the process by restarting AppleTalk with the desired connection method. It also limits compatibility with Apple cards and those from other vendors you select to support.
Multicast addresses for zone names hashed to same index value
Date Written: 3/3/92
Last reviewed: 6/14/93
What’s the strategy for assigning a multicast address if two different zone names hash to the same index value? How do two different routers synchronize the multicast address assignment in the case of hash synonyms?
___
It’s quite possible that two zone names will hash to the same index. Networks which have zone names that hash to synonyms will have the packets resolved at the receiving nodes. Packets that get delivered to the wrong zone because of identical multicast addresses will be handled by NBP (Name Binding Protocol), which will see that the destination zone name is different if the target zone is the zone synonym.
Start & end for extended networks with single number for range
Date Written: 3/3/92
Last reviewed: 6/14/93
If a network is assigned a single network number for a network number range—for example, 3—how is the network number range start and end represented? It is 3-3 or 3-0 or is it anything else?
___
On an extended network type such at TokenTalk or EtherTalk, a network range of a single network number is entered as both the start and end of the range. For example, a network range of 3 is such that netLo is 3 and netHi is also 3.
Phase 2 routers must support Split Horizon technique
Date Written: 3/3/92
Last reviewed: 6/14/93
RTMP data packets sent by all routers on an internet use the Split Horizon technique or the No-Split Horizon. Does it matter if different routers use different techniques?
___
The AppleTalk router, version 2.0, implements the Split Horizon technique. All Phase 2 routers MUST implement the Split Horizon technique for compatibility with AppleTalk. For a description of the Split Horizon technique, refer to Inside AppleTalk, 2nd ed., 5-11.
AppleTalk routers and Route Data Request (RDR) packets
Date Written: 3/3/92
Last reviewed: 6/14/93
Does an AppleTalk router initiate a Route Data Request (RDR) packet? If so, when?
___
A router is free to send a Route Data Request packet at any time. A particularly good time to send an RDR packet is when a router has not heard from another router in some time.
NW 580 - Token Ring Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
New Q&As this month:
NetCopy procedure replaces TokenTalk CopyNuBus
NetCopy procedure replaces TokenTalk CopyNuBus
Date Written: 9/23/92
Last reviewed: 6/14/93
The TokenTalk Programmer’s Guide describes a routine called CopyNuBus. This routine is not in the IPCGlue.o file dated 3/4/92 that I got off a Developer CD. Has this routine been replaced by something else, and if so, what is the calling sequence of the new routine?
___
The TokenTalk Programmer’s Guide hasn’t been updated to reflect the fact that the CopyNuBus routine has been replaced by the more robust NetCopy procedure. The prototype for the NetCopy routine is
short NetCopy(tid_type srcTID, void *srcAddress, tid_type dstTID, void *dstAddress,
unsigned long bytecount);
Note the addition of the source and the destination TIDs. NetCopy will copy from a source virtual address to a target virtual address and is a safe way to move data across the NuBus. Both the source and destination virtual addresses can be paged out to disk in a VM environment. NetCopy will cause these pages to be brought back into memory before the copy is performed. A result of zero is returned if NetCopy is successful.
This information comes from the A/ROSE Programmer’s Guide. You should get a copy of this guide and referring to it regarding A/ROSE programming questions instead of referencing the TokenTalk Programmer’s Guide. A/ROSE has been a fast evolving piece of software. Always refer to the latest Developer CD for the latest revision.
TokenTalk LLCBadList and LLCTruncated
Date Written: 9/24/91
Last reviewed: 6/14/93
When a list-directed receive is queued to TokenTalk’s implementation of Logical Link Control (LLC) with a total data size less than the active frame size, LLCBadList is returned when the receive completes. If a nonlist-directed receive is used, and the buffer size is less than a frame size, LLCTruncated is returned. Why aren’t the same error codes (LLCTruncated) returned as the condition is the same?
___
The LLCBadList error results because of an undocumented limitation imposed on the number of lists allowed in a list-directed receive. It’s likely that you’ve specified a list array with greater than eight elements. When the list is passed to LLCReceive, a check is made on the list array if one is used. If more than eight elements are in the list, the LLCBadList error is returned immediately with no processing of the incoming data.
On the other hand, if a nonlist-directed receive is used, the LLCReceive call is queued into the task list. The present TokenTalk LLC implementation doesn’t support partial reads of large data frames, so if it turns out that the buffer size is smaller than the frame size, only the information that fits into the buffer is returned. The remaining information is discarded. The error condition LLCTruncated is returned to indicate that this event occurred.
How to get burned-in & locally administered Token Ring addresses
Date Written: 12/11/91
Last reviewed: 12/12/91
How can I read the “burned-in” address from the TokenTalk NB card? How about for the locally administered address?
__
To access the burned-in address, use the TTGetDefaultParms selector when calling the TTUtil function pointer. On return, the record structure, TRInit, will contain the value of the “burned-in” address in the field NodeAddr. Use the TTGetBootParms selector to obtain the equivalent information from the TokenTalk Prefs file, that information which has been locally set.
Note the following #defines to include in your TTUtil.h header file:
#define TTGetBootParms 11 /* Return TRInit parameters to use on next boot */
/*
* The TTGetDefaultParms and TTGetBootParms returns a pointer to the
* parameter structure, or zero if no parameters could be returned. The
* parameter structure returned should be released by the caller by calling
* DisposPtr when done.
*/
TokenRing NB 4/16 Card and “promiscuous” mode support
Date Written: 12/6/91
Last reviewed: 6/14/93
Can the IBM chipset which is on Apple’s new TokenRing NB 4/16 Card be programmed to go into “promiscuous” mode? I would like to write a Sniffer application which runs on the new card.
___
At present, the present design of the IBM mini-card is such that the chipset cannot be programmed to run in promiscuous mode. A request has been submitted to IBM to allow the chipset to be placed into this mode. There is no date as to when such functionality will become available.
TokenTalk maximum transmit buffer size
Date Written: 12/19/91
Last reviewed: 6/14/93
In reviewing the 'llcp' resource for the new TokenTalk 4/16 NuBus card, I noticed that the maximum receive frames size has been changed to 0x1170 or 4464 bytes. If this is correct, what is the maximum transmit size (used to be 1509 bytes)?
___
The change is for real. It was implemented at the request of developers like yourself. The change affects all Apple’s TokenTalk products provided that TokenTalk Prep 2.4 is present.
The maximum transmit buffer size depends on the 'llcp' resource in the TokenTalk Prep or (TokenTalk Prefs file if one is available). Within the 'llcp' resource is a buffer size value used to initialize the size of the receive/transmit buffers. For file versions 2.2 and earlier, the factory limit was 1509 bytes. For TokenTalk Prep version 2.4, the buffer size is set to 4464 bytes.
NW 585 - X.25 and X.400 Q&As
Networking
Revised by: Developer Support Center September 1993
Written by: Developer Support Center October 1990
This Technical Note contains a collection of Q&As relating to a specific topic—questions you’ve sent the Developer Support Center (DSC) along with answers from the DSC engineers. While DSC engineers have checked the Q&A content for accuracy, the Q&A Technical Notes don’t have the editing and organization of other Technical Notes. The Q&A function is to get new technical information and updates to you quickly, saving the polish for when the information migrates into reference manuals.
Q&As are now included with Technical Notes to make access to technical updates easier for you. If you have comments or suggestions about Q&A content or distribution, please let us know by sending an AppleLink to DEVFEEDBACK. Apple Partners may send technical questions about Q&A content to DEVSUPPORT for resolution.
Which A/ROSE version to use
Date Written: 6/2692
Last reviewed: 6/14/93
What should I be doing with A/ROSE versions? My application links with X.25_Interface_Library.o, IPCGlue.o, and FSDES.o. Should I be using the latest IPCGlue.o that is on the Developer CD, or should I use the one that came with the X.25 Developers Kit? Also what about A/ROSE itself? Can I safely replace the existing one in my Extensions folder with the latest one from the CD? If I do should I relink the app with the corresponding IPCGlue.o? What about the MacX25 Admin? Will it be happy with the latest copy of A/ROSE in the Extensions folder? My code resources also link with IPCGlue.o. I assume I should link the code resources and app with the same IPCGlue.o, right?
___
Changes to A/ROSE are typically made to A/ROSE itself. In general, you should follow the guideline that you describe—link with the library file for the version of A/ROSE you plan to ship with. Interestingly, the A/ROSE IPCGlue.o file shipped with MacX25 1.0.1 is still fine for linking with. You should also relink your application with the (MacX25 1.1) X.25_Interface_Library.o as there are a number of memory management bugs fixed between 1.0.1 and 1.1, some of which caused system crashes.
Over the past several years, new releases of A/ROSE have been made to fix bugs and to support new hardware. If you plan to be compatible with new CPUs, you might want to supply the latest release of A/ROSE.
Locking X.25 segments
Date Written: 6/2692
Last reviewed: 6/14/93
Are there any of the X.25 segments from X25_Interface_Library.o that need to be locked or should be specified as resident in my application’s 'res!' resource? In, particular I am wondering about the segment X25_VBL.
___
The X25_VBL segment contains code that is executed at interrupt time, and the rules for dealing with interrupt driver code should be followed—that is, the VBL code and VBL task record should be locked down.
Segmenting data for X25_Write
Date Written: 6/2692
Last reviewed: 6/14/93
When writing data with the X25_Write routine, I seem to need to break up the data to write according to the current packet size and then make separate calls for each data chunk/packet. I had hoped the X25_Write would have figured that out by itself. Am I missing something? What about when using X25_Read? Should I be reassembling packets with the M_Bit set, into big chunks of data?
___
No, At present, the X25_Write routine does not do anything very useful in the domain of segmentation and reassembly of X.25 data. The routine only handles the segmentation and assembly of one packet’s worth of data. Unfortunately, the same comment applies to the X25_Read routine.
Depending on A/ROSE to correctly queue a message
Date Written: 6/2692
Last reviewed: 6/14/93
Is it possible to intercept an A/ROSE message from the X.25 server that was destined for the X.25_Interface_Library? The server and the client are running on the same machine, and I connect to the server with X25_Server_Connect(gTcb, connect_via_best).
___
A/ROSE is dependable for delivering messages to your task, that are sent to your task, and not to other tasks. To date, there have not been any problems reported on this subject.
Translating 8-bit Macintosh text to 7-bit ASCII
Date Written: 12/20/90
Last reviewed: 6/24/93
Is there an Apple-recommended method for converting 8-bit Apple text characters to that which can be sent over 7-bit media while observing X.400 rules, and only submit 7-bit text into the x.400 IA5Text body parts?
___
MacPAD used to support only 7-bit file transfers, but it’s now possible to translate from 8 bit characters to 7 bit.
Where to find X.400 & X.500 references
Date Written: 1/23/91
Last reviewed: 6/14/93
Where can I find documentation on the X.400 and X.500 electronic-mail standard?
___
There are a few interesting articles about X.400 in the Technical Information Library on AppleLink. One of them mentions that Apple has a forthcoming X.400 solution that is an X.400-compliant MTA (Message Transfer Agent) that runs on any modular Macintosh under System 7. It includes the seven layers of the OSI model. It works either over X.25 (on top of the MacX25 product) or over 802.3. (This is the most used link in the U.S.) It lets Macintosh users gain access to public X.400 networks or to connect to their private X.400 backbone.
For standards and specifications on X.400 and X.500, check with your local library for an IEEE periodical index. IEEE documents this type of stuff fairly regularly.
Feasibility of MacX25 AppleTalk internet routers
Date Written: 3/26/91
Last reviewed: 6/24/93
What’s the feasibility of internet routers for AppleTalk networks over MacX25?
___
Internet routers for AppleTalk networks over MacX25 are not only feasible, they’re available. Apple’s internet router 3.0, with the X.25 internet router extension, provides this function.
Providing general “listeners” on MacX25 servers
Date Written: 3/26/91
Last reviewed: 6/14/93
Is it feasible to develop general “listeners” on the MacX25 servers? This would allow users to connect to MacX25 servers and request specific services to be provided. Other non-Macintosh systems could also communicate with such listeners.
___
MacX25 does indeed provide a listener agent. Please refer to the MacX25 product documentation. If, however, you want to develop your own listener, one could be provided via access to A/ROSE.
How to increase Macintosh X.25 user list size
Date Written: 7/25/91
Last reviewed: 6/14/93
How do we go beyond the Macintosh X.25 user list entry limit of 256?
___
The size of the X.25 user list can be modified by modifying the 'Maxu' resource in the X.25 Admin program using ResEdit. If you’re using the latest revision of ResEdit version 2.1, a template for the 'Maxu' resource exists to assist with this modification. The other recommended change is to increase the program partition size of X.25 Admin by 32 bytes for each additional user to ensure that there is enough memory to hold all of the names. Note that this change does not increase the number of simultaneous connections.